I am trying to publish an artifact to Artifactory using Java.
Here is the code.
public static void publishToArtifactoryPro(String groupId,
String artifactId,
String version,
Collection artifacts) throws JarMigrationServiceException{
// create an ivy instance
IvySettings ivySettings = new IvySettings();
ivySettings.setDefaultCache(new File("ivy/cache"));
// use the biblio resolver, if you consider resolving
// POM declared dependencies
IBiblioResolver br = new IBiblioResolver();
br.setM2compatible(true);
br.setUsepoms(true);
br.setName("ibiblio");
br.setRoot(Constants.ARTIFACTORY_PRO_RELEASE_LOCAL);
ivySettings.addResolver(br);
ivySettings.setDefaultResolver(br.getName());
Ivy ivy = Ivy.newInstance(ivySettings);
//you always need to resolve before you can retrieve
ResolveOptions ro = new ResolveOptions();
// this seems to have no impact, if you resolve by module descriptor (in contrast to resolve by ModuleRevisionId)
ro.setTransitive(true);
// if set to false, nothing will be downloaded
ro.setDownload(true);
// 1st create an ivy module (this always(!) has a "default" configuration already)
DefaultModuleDescriptor md = DefaultModuleDescriptor.newDefaultInstance(
// give it some related name (so it can be cached)
ModuleRevisionId.newInstance(
groupId,
artifactId+"-envelope",
version
)
);
// 2. add dependencies for what we are really looking for
ModuleRevisionId ri = ModuleRevisionId.newInstance(
groupId,
artifactId,
version
);
// don't go transitive here, if you want the single artifact
DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, ri, false, false, false);
// map to master to just get the code jar. See generated ivy module xmls from maven repo
// on how configurations are mapped into ivy. Or check
// e.g. http://lightguard-jp.blogspot.de/2009/04/ivy-configurations-when-pulling-from.html
dd.addDependencyConfiguration("default", "master");
md.addDependency(dd);
// now resolve
ResolveReport rr = null;
try {
rr = ivy.resolve(md,ro);
if (rr.hasError()) {
throw new RuntimeException(rr.getAllProblemMessages().toString());
}
}
catch (ParseException e) {
throw new JarMigrationServiceException(e.getMessage(), e);
}
catch (IOException e) {
throw new JarMigrationServiceException(e.getMessage(), e);
}
try {
ivy.publish(
ModuleRevisionId.newInstance(groupId, artifactId, version),
artifacts,
"artifactory-publish",
new PublishOptions()
// this is from the envelop module
.setConfs(new String[]{"default"})
);
}
catch (IOException e) {
throw new JarMigrationServiceException(e.getMessage(), e);
}
}
Here is the error:
Exception in thread "main" java.lang.IllegalStateException: ivy file not found in cache for com.mycompany#MAO;1.1.2: please resolve dependencies before publishing (ivy/cache/resolved-com.mycompany-MAO-1.1.2.xml)
at org.apache.ivy.core.publish.PublishEngine.publish(PublishEngine.java:105)
at org.apache.ivy.Ivy.publish(Ivy.java:600)
at com.mycompany.is.dt.Utilities.JarMigrationUtility.publishToArtifactoryPro(JarMigrationUtility.java:96)
at com.mycompany.is.dt.controllers.JarMigrationService.main(JarMigrationService.java:29)
So I am confused because it says ivy file not found in cache but you can see that I am setting the cache here ivySettings.setDefaultCache(new File("ivy/cache")); And when I go to ivy/cache/com/mycompany/MAO I see the jar there... Any ideas?
Related
I am creating a Rhapsody JavaAPI plugin that will clean the current project files and copy in a fresh model. This is to have a fresh working copy for developers so they do not have to close rhapsody and copy in the clean models manually.
My dilemma is when i close the active project, it removes it from the rhapsody view as expected. When I try reloading the new rpy file, the view does not change nor is the model reload.
How would I go about reloading the project?
Here is my plugin (note the class call works fine. Its in the method clean that I am having issues).
public class CMMCleaner {
private Path rootDir;
private Path rpyFile;
private IRPApplication rpyApp;
public CMMCleaner(final Path rootDir, final IRPApplication rpyApp) {
this.rootDir = rootDir;
if (!Files.exists(rootDir)) throw new IllegalArgumentException(rootDir + " does not exist");
this.rpyApp = rpyApp;
this.rpyFile = Paths.get(this.rpyApp.activeProject().getCurrentDirectory()).resolve(this.rpyApp.activeProject().getFilename());
}
public void clean() {
try {
rpyApp.activeProject.close();
Path cleanDir = this.rootDir.resolve("CMM_starting_model");
Path oldDir = this.rootDir.resolve("CMM_model");
Files.walk(oldDir)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
Files.walk(cleanDir)
.filter(p -> Files.isRegularFile(p))
.forEach(cleanFile -> {
Path path = oldDir.resolve(cleanDir.relativize(cleanFile));
try {
Files.createDirectories(path.getParent());
Files.copy(cleanFile, path, StandardCopyOption.REPLACE_EXISTING);
} catch (Exception ex) {
ex.printStackTrace();
}
});
rpyApp.openProject(this.rpyFile.toAbsolutePath().toString());
rpyApp.insertProject(this.rpyFile.toAbsolutePath().toString());
rpyApp.activeProject();
rpyApp.refreshAllViews();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
No Exceptions are thrown, but as stated the project does close and I can visually see the files being deleted and copied in, but nothing happens in rhapsody after that.
I was able to solve the problem by removing the following lines:
rpyApp.activeProject.close(); and rpyApp.insertProject(this.rpyFile.toAbsolutePath().toString());
I'm having trouble using tools.jar present in jdk1.8.0_121/lib/tools.jar.
My $JAVA_HOME is set to:
# echo $JAVA_HOME
/usr/local/java/jdk1.8.0_121
The path to tools.jar is :
# ls /usr/local/java/jdk1.8.0_121/lib/tools.jar
/usr/local/java/jdk1.8.0_121/lib/tools.jar
And I use the following java executable to run the code:
/usr/local/java/jdk1.8.0_161/bin/java
But, when I access the VirtualMachine class, it throws
Caused by: java.lang.ClassNotFoundException: com.sun.tools.attach.VirtualMachine
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_161]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_161]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338) ~[na:1.8.0_161]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_161]
... 72 common frames omitted
Can someone explain why Java is not able to find lib/tools.jar in its classpath & What can I do to correct this behaviour?
To run on my local machine, I've added the following dependency in my pom:
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.8</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
But, when I deploy it on the server, this jar is not packaged due to system scope & neither does it find the jar on the server's jdk path.
Isn't it supposed to find all the jdk jars automatically?
I've also tried to add env variable $JAVA_HOME in the class-path entry of jar's MANIFEST file as follows:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: pankajsinghal
Class-Path: $JAVA_HOME/lib/
Created-By: Apache Maven 3.5.4
Build-Jdk: 1.8.0_181
But, this is also not working. Also, I don't want to add this lib's jar in my code explicitly as it's a JDK lib and I guess the proper way to access this would be from the system's JDK path itself. So, looking for a solution in this direction itself.
Any help is really appreciated.
You can try it like this:
java -cp "/path/your.jar:/usr/local/java/jdk1.8.0_121/lib/tools.jar" your.MainClass
or Refer to the following:
The type "com.sun.tools.javac.util.Assert" is not accessible
Hopefully it helped you.
You have to add that jar in project properties. In eclipse, To Add this Jar to your build path Right click the Project > Build Path > Configure build path> Select Libraries tab > Click Add External Libraries > Select the Jar file.
you can directly add toos.jar to your current classLoader, but it just an idea.
File getJar = new File(folderLibsPath + File.separator + "tools.jar");
URLClassLoader classLoaderExt = (URLClassLoader) this.getClassLoader();
URL jarUrl = getJar.toURI().toURL();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoaderExt, jarUrl);
referenced from:How to load JAR files dynamically at Runtime?
and don't forget to load the attach.so (or attach.dll)
by System.load(absPath) or System.loadLibrary(dllName)
File attachedDLL = new File(folderLibFilePath);
if (attachedDLL.exists()) {
System.load(attachedDLL.getAbsolutePath());
}
I think we had got the same issue, and this code works for my case.
Also, there is another way to add tools.jar into classpath, but actually they did the same thing:
public void onEnable() throws Exception {
URLClassPath ucp = (URLClassPath) Reflection.getPrivateField("ucp", this.getClassLoader().getParent()); // reflect the subClass of URLClassLoader
File getJar = new File(folderLibsPath + File.separator + "tools.jar");
URL jarUrl = getJar.toURI().toURL();
ucp.addURL(jarUrl); // or just change its "URLs" field by put your jarURL in its Stack
}
But it should be mention that, this way the Java will use the AppClassLoader(SystemClassLoader) to load the tools.jar (also the invoker - your application will). This may have a bad effect on your original class initialization if you use CustomClassLoader. (because depending on the Java Parent Delegation Model, the superClassLoader cannot know which class load by its subClassLoader).
So if you are developing a plugin under a customClassLoader (the subclass of system classloader), the classpath in AppClassLoader should be removed (which means let custom PluginClassLoader to load it, or not its super one) after your VM was detached.
here I used reflection to accomplished.
public class Main {
public void onEnable() throws Exception {
/** load attach.dll */
System.loadLibrary("attach");
/** load tools.jar */
URLClassPath ucp = (URLClassPath) Reflection.getPrivateField("ucp", this.getClassLoader().getParent());
File getJar = new File(folderLibsPath + File.separator + "tools.jar");
URL jarUrl = getJar.toURI().toURL();
ucp.addURL(jarUrl);
/** attach, load, detach VM */
VirtualMachine vm;
vm = VirtualMachine.attach(this.getPid());
// if the current jar itself is the agent
vm.loadAgent(new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getAbsolutePath());
vm.detach();
/** change the classLoader back to your custom */
changeClassLoaderBack();
/** unload native DLL Lib */
unloadNativeLibs(); // or you can add a condition to unload attach.dll only
}
public void changeClassLoaderBack() {
URLClassPath ucp = (URLClassPath) Reflection.getPrivateField("ucp", this.getClassLoader().getParent());
/** reset field path */
List<?> path = (ArrayList<?>) Reflection.getPrivateField("path", ucp);
List<URL> newPath = new ArrayList<>();
path.forEach((v) -> {
if(!((URL)v).getPath().contains("toos.jar") && !((URL)v).getPath().contains(this.getPlugin().getName())) {
newPath.add(((URL)v));
}
});
Reflection.setPrivateField("path", ucp, newPath);
/** reset field URLs */
Reflection.setPrivateField("urls", ucp, new Stack<URL>());
/** reset fields loader and LMAP */
List<Object> newLoader = new ArrayList<>();
Map<Object, Object> newLMAP = new HashMap<>();
((HashMap<?,?>)Reflection.getPrivateField("lmap", ucp)).forEach((k,v) -> {
if (!((String)k).contains("tools.jar") && !((String)k).contains(this.getPlugin().getName())) {
newLMAP.put(k, v);
newLoader.add(v);
};
});
Reflection.setPrivateField("lmap", ucp, newLMAP);
Reflection.setPrivateField("loaders", ucp, newLoader);
}
private String getPid() {
RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
String pid = bean.getName();
if (pid.contains("#")) {
pid = pid.substring(0, pid.indexOf("#"));
}
return pid;
}
private void unloadNativeLibs(ClassLoader unloadDLLfromWhichLoader) {
try {
ClassLoader classLoader = unloadDLLfromWhichLoader;
Field field = ClassLoader.class.getDeclaredField("nativeLibraries");
field.setAccessible(true);
Vector<?> libs = (Vector<?>) field.get(classLoader);
Iterator<?> it = libs.iterator();
Object o;
while (it.hasNext()) {
o = it.next();
Method finalize = o.getClass().getDeclaredMethod("finalize", new Class[0]);
finalize.setAccessible(true);
finalize.invoke(o, new Object[0]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Reflection {
public static Object getPrivateField(String fieldName, Object object) {
Field field;
Object o = null;
try {
field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
o = field.get(object);
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
return o;
}
public static void setPrivateField(String fieldName, Object object, Object newField) {
Field field;
try {
field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, newField);
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
hope it can help you at some points
I have this code:
ThreadPoolExecutor t;
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
System.out.println("root" + root.getLocation().toOSString());
Runnable runnable = new Runnable() {
public void run() {
try {
IPath projectDotProjectFile = new Path("C:\\Users\\rezbi\\eclipse-workspace\\AutoRefactor-master\\AutoRefactor-master" + "/.project");
IProjectDescription projectDescription = workspace.loadProjectDescription(projectDotProjectFile);
IProject project = workspace.getRoot().getProject(projectDescription.getName());
JavaCapabilityConfigurationPage.createProject(project, projectDescription.getLocationURI(), null);
//project.create(null);
} catch (CoreException e) {
e.printStackTrace();
}
}
};
// and now get the workbench to do the work
final IWorkbench workbench = PlatformUI.getWorkbench();
workbench.getDisplay().syncExec(runnable);
IProject[] projects = root.getProjects();
for(IProject project: projects){
System.out.println(project.getName());
}
I followed the instructions as mentioned in the link below:
http://techdc.blogspot.com/2015/01/eclipse-workbench-has-not-been-created.html
I added the following dependencies only:
org.apache.felix.gogo.command
org.apache.felix.gogo.runtime
org.apache.felix.gogo.shell
org.eclipse.equinox.console
org.eclipse.osgi
Unfortunately it is giving plugin dependency hello - I run the app, I get unresolved dependencies, I add the dependencies and there are more unresolved dependencies. And if I select "add required bundles" from run configuration, then I get "Workbench has not been created yet. Error while creating OSGi modules"
So is there an easier way to get around this?
Update:
How I am creating the project is here:
http://codeandme.blogspot.com/2012/02/creating-headless-application.html
So this is a plugin project.
And to run I right click on the manifest file. Select run as and then osgi framework. Note: I also tried including the plugin dependencies from run configuration. Then I tried to run > Eclipse Application. Either way I get the same result : workbench not created yet.
In the same java class the following code works:
public Object start(IApplicationContext context) throws Exception {
// TODO Auto-generated method stub
//String PACKAGE_NAME = "cucumber";
//final IPackageFragment packageFragment = JavaCoreHelper.getPackageFragment(PACKAGE_NAME);
//System.out.println(packageFragment);
//final ICompilationUnit cu = packageFragment.createCompilationUnit("Application5.java", "", true, null);
//IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
//IProject m_project = root.getProject("cucumber");
//System.out.println("m_project "+m_project);
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
System.out.println("HELLO ");
IProject[] projects = root.getProjects();
for (IProject project : projects) {
try {
printProjectInfo(project);
} catch (CoreException e) {
e.printStackTrace();
}
}
// createAProject();
//System.out.println("test "+root.getProject(name));
return null;
}
But as soon as I try accessing workbench things break.
We have a legacy system that has a admim module that allows users to upload jar files. After the upload, the jar file is validated and if not compliant to internal rules, it is deleted.
The problem is that windows is throwing an exception telling that the file "is already being used by another process." (when I call Files.delete(tmpJar);). I'm not able to identify why the file is open. Seems to me that I have closed everything.
First, we are using primefaces (4.0) to upload the file. Primefaces relies on commons-fileupload (1.3.1). It call the following method:
public void handleFileUpload(FileUploadEvent event) {
Path tmpJar = null;
try {
tmpJar = Files.createFile(Paths.get(event.getFile().getFileName()));
Files.write(tmpJar, event.getFile().getContents());
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
if (tmpJar != null) {
try {
this.validateJar(tmpJar.toString());
Files.delete(tmpJar);
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
Before NIO Files.write, I was using "standard" java IO classes. The problem isn't related to the above code, because if I comment the call to validateJar, Files.delete(tmpJar) is executed without problems and the file is removed. So, the problem is related with the code below, but I can't find where...
Job is an internal class, basically a simple POJO. "jobAnnotation" is a custom annotation to identify Jobs. I have shortened the code, but the essencial parts are preserved.
private List<Job> validateJar(final String jarPath) throws IOException {
List<Job> jobs = new ArrayList<Job>();
try (JarFile jarFile = new JarFile(jarPath)) {
URL[] jars = { new URL("file:" + jarPath) };
ClassLoader jobClassLoader = URLClassLoader.newInstance(jars, this.getClass().getClassLoader());
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String className = jarEntry.getName();
Class<?> classToLoad;
try {
classToLoad = Class.forName(className, true, jobClassLoader);
} catch (Exception e1) {
LOGGER.error(e1.getMessage(), e1);
continue;
}
if (classToLoad.isAnnotationPresent(jobAnnotation)) {
String vlr = null;
try {
Class<?> jobClass = (Class<?>) Class.forName(classToLoad.getCanonicalName(), true, jobClassLoader);
Annotation annotation = jobClass.getAnnotation(jobAnnotation);
Method method = annotation.getClass().getMethod("getValue");
vlr = ((String) method.invoke(annotation, new Object[0]));
} catch (Exception e1) {
LOGGER.error(e1.getMessage(), e1);
}
Job job = new Job();
job.setEnabled(true);
job.setJarfile(jarPath);
job.setClassName(classToLoad.getName());
Parameter parameter = new Parameter();
parameter.setRequired(true);
parameter.setName("name");
parameter.setValue(vlr);
job.addParameter(parameter);
jobs.add(job);
}
}
} catch (IOException e) {
throw e;
}
return jobs;
}
Before using try-with-resources, I was using regular try-catch-finally to close the JarFile, thats the only thing that has a explicit close method. Probably is the classloading that is holding the file open, but I don't know how to close it.
I did some searches, and I found that I can't unload classes (Unloading classes in java?).
So, the problem is, how do I release it? Or how can I remove the file?
BTW, I'm using java 1.7.0_71, jboss 7.1.1, windows 7 (64).
The URLClassLoader class already has a close() method. The close() method will close any Jar file that are opened with the URLClassLoader. This should prevent the "file already in use" exception.
File is already being used by another process. says that it could be not your fault, maybe just another application is used that file. You can check this question to find a process which is used your file.
Some Virus scanner software take a long time in checking JARs. Try to disable the Virusscanner. Other candidates can be the Windows indexer process, or the explorer.exe itself. When you don't find any reason for the file lock, try a delay between the validation and the deletion. Maybe you need a loop with multiple tries.
I'd like to use Google Reflections to scan classes from the compiled project from my Maven plugin. But plugins by default don't see the compiled classes of the project. From Maven 3 documentation I read:
Plugins that need to load classes from the compile/runtime/test class path of a project need to create a custom URLClassLoader in combination with the mojo annotation #requiresDependencyResolution.
Which is a bit vague to say the least. Basically I would need a reference to a classloader that loads the compiled project classes. How do I get that?
EDIT:
Ok, the #Mojo annotation has requiresDependencyResolution parameter, so that's easy but still need the correct way to build a classloader.
#Component
private MavenProject project;
#SuppressWarnings("unchecked")
#Override
public void execute() throws MojoExecutionException {
List<String> classpathElements = null;
try {
classpathElements = project.getCompileClasspathElements();
List<URL> projectClasspathList = new ArrayList<URL>();
for (String element : classpathElements) {
try {
projectClasspathList.add(new File(element).toURI().toURL());
} catch (MalformedURLException e) {
throw new MojoExecutionException(element + " is an invalid classpath element", e);
}
}
URLClassLoader loader = new URLClassLoader(projectClasspathList.toArray(new URL[0]));
// ... and now you can pass the above classloader to Reflections
} catch (ClassNotFoundException e) {
throw new MojoExecutionException(e.getMessage());
} catch (DependencyResolutionRequiredException e) {
new MojoExecutionException("Dependency resolution failed", e);
}
}