From 4233e023543e4913c5346db042ac9884c19c911d Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Wed, 26 Sep 2012 19:25:22 +0400 Subject: [PATCH] Support maven 3 --- plugins/maven/maven.iml | 1 + .../server/Maven3ServerEmbedderImpl.java | 177 +++++++++++++++--- .../maven/server/MyFileProfileActivator.java | 118 ++++++++++++ .../maven/server/embedder/FieldAccessor.java | 4 +- .../idea/maven/server/MavenServerManager.java | 19 +- 5 files changed, 287 insertions(+), 32 deletions(-) create mode 100644 plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MyFileProfileActivator.java diff --git a/plugins/maven/maven.iml b/plugins/maven/maven.iml index 96b9d4ef6736..12426a10325c 100644 --- a/plugins/maven/maven.iml +++ b/plugins/maven/maven.iml @@ -54,6 +54,7 @@ + diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java index c66c35f7dffd..d576f6f5bebf 100644 --- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java +++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java @@ -16,7 +16,19 @@ package org.jetbrains.idea.maven.server; import com.intellij.util.SystemProperties; +import gnu.trove.THashSet; import org.apache.maven.cli.MavenCli; +import org.apache.maven.model.Activation; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; +import org.apache.maven.model.profile.DefaultProfileInjector; +import org.apache.maven.profiles.activation.*; +import org.apache.maven.project.DefaultProjectBuilderConfiguration; +import org.apache.maven.project.ProjectBuilderConfiguration; +import org.apache.maven.project.interpolation.AbstractStringBasedModelInterpolator; +import org.apache.maven.project.interpolation.ModelInterpolationException; +import org.apache.maven.project.path.DefaultPathTranslator; +import org.apache.maven.project.path.PathTranslator; import org.apache.maven.settings.Settings; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; import org.apache.maven.settings.building.SettingsBuilder; @@ -25,11 +37,15 @@ import org.apache.maven.settings.building.SettingsBuildingRequest; import org.codehaus.plexus.DefaultPlexusContainer; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.classworlds.ClassWorld; +import org.codehaus.plexus.context.ContextException; +import org.codehaus.plexus.context.DefaultContext; import org.codehaus.plexus.logging.BaseLoggerManager; import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.model.*; +import org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator; import org.jetbrains.idea.maven.server.embedder.FieldAccessor; import java.io.File; @@ -65,34 +81,27 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven } }; - List methods = Arrays.asList("initialize", - "cli", - "properties", - "container"); - Class cliRequestClass = null; - Class[] classes = MavenCli.class.getDeclaredClasses(); - for (Class each : classes) { - if (each.getSimpleName().equals("CliRequest")) { - cliRequestClass = each; - break; - } + try { + cliRequestClass = MavenCli.class.getClassLoader().loadClass("org.apache.maven.cli.MavenCli$CliRequest"); + } + catch (ClassNotFoundException e) { + throw new RuntimeException("Class \"org.apache.maven.cli.MavenCli$CliRequest\" not found"); } - if (cliRequestClass == null) throw new RuntimeException("'CliRequest' class not found among '" + Arrays.toString(classes) + "'"); Object cliRequest; try { - List commandLineOptions = new ArrayList(settings.getUserProperties().size()); + String[] commandLineOptions = new String[settings.getUserProperties().size()]; + int idx = 0; for (Map.Entry each : settings.getUserProperties().entrySet()) { - commandLineOptions.add("-D" + each.getKey() + "=" + each.getValue()); + commandLineOptions[idx++] = "-D" + each.getKey() + "=" + each.getValue(); } - String[] commandLineOptionsArray = commandLineOptions.toArray(new String[commandLineOptions.size()]); Constructor constructor = cliRequestClass.getDeclaredConstructor(String[].class, ClassWorld.class); constructor.setAccessible(true); - cliRequest = constructor.newInstance(commandLineOptionsArray, classWorld); + cliRequest = constructor.newInstance(commandLineOptions, classWorld); - for (String each : methods) { + for (String each : new String[]{"initialize", "cli", "properties", "container"}) { Method m = MavenCli.class.getDeclaredMethod(each, cliRequestClass); m.setAccessible(true); m.invoke(cli, cliRequest); @@ -112,7 +121,7 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven } // reset threshold - myContainer = FieldAccessor.get(MavenCli.class, cli, "container"); + myContainer = FieldAccessor.get(MavenCli.class, cli, "container"); myContainer.getLoggerManager().setThreshold(settings.getLoggingLevel()); myMavenSettings = buildSettings(FieldAccessor.get(MavenCli.class, cli, "settingsBuilder"), @@ -169,6 +178,13 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven @Override public MavenArtifact resolve(@NotNull MavenArtifactInfo info, @NotNull List remoteRepositories) throws RemoteException, MavenServerProcessCanceledException { + //DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper); + // + //MavenExecutionResult result = myImpl.resolveProject(file, + // new ArrayList(activeProfiles), + // Arrays.asList(listener)); + //return createExecutionResult(file, result, listener.getRootNode()); + throw new UnsupportedOperationException(); } @@ -204,18 +220,22 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven myContainer.dispose(); } - @Override public void clearCaches() throws RemoteException { - throw new UnsupportedOperationException(); + // do nothing } - @Override - public void clearCachesFor(MavenId projectId) throws RemoteException { - throw new UnsupportedOperationException(); + public void clearCachesFor(final MavenId projectId) throws RemoteException { + // do nothing } - public static MavenModel interpolateAndAlignModel(MavenModel model, File basedir) { - throw new UnsupportedOperationException(); + public static MavenModel interpolateAndAlignModel(MavenModel model, File basedir) throws RemoteException { + Model result = MavenModelConverter.toNativeModel(model); + result = doInterpolate(result, basedir); + + PathTranslator pathTranslator = new DefaultPathTranslator(); + pathTranslator.alignToBaseDirectory(result, basedir); + + return MavenModelConverter.convertModel(result, null); } public static MavenModel assembleInheritance(MavenModel model, MavenModel parentModel) { @@ -225,8 +245,111 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven public static ProfileApplicationResult applyProfiles(MavenModel model, File basedir, Collection explicitProfiles, - Collection alwaysOnProfiles) { - throw new UnsupportedOperationException(); + Collection alwaysOnProfiles) throws RemoteException { + Model nativeModel = MavenModelConverter.toNativeModel(model); + + List activatedPom = new ArrayList(); + List activatedExternal = new ArrayList(); + List activeByDefault = new ArrayList(); + + List rawProfiles = nativeModel.getProfiles(); + List expandedProfilesCache = null; + + for (int i = 0; i < rawProfiles.size(); i++) { + Profile eachRawProfile = rawProfiles.get(i); + + boolean shouldAdd = explicitProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId()); + + Activation activation = eachRawProfile.getActivation(); + if (activation != null) { + if (activation.isActiveByDefault()) { + activeByDefault.add(eachRawProfile); + } + + // expand only if necessary + if (expandedProfilesCache == null) expandedProfilesCache = doInterpolate(nativeModel, basedir).getProfiles(); + Profile eachExpandedProfile = expandedProfilesCache.get(i); + + for (ProfileActivator eachActivator : getProfileActivators(basedir)) { + try { + if (eachActivator.canDetermineActivation(eachExpandedProfile) && eachActivator.isActive(eachExpandedProfile)) { + shouldAdd = true; + break; + } + } + catch (ProfileActivationException e) { + Maven3ServerGlobals.getLogger().warn(e); + } + } + } + + if (shouldAdd) { + if (MavenConstants.PROFILE_FROM_POM.equals(eachRawProfile.getSource())) { + activatedPom.add(eachRawProfile); + } + else { + activatedExternal.add(eachRawProfile); + } + } + } + + List activatedProfiles = new ArrayList(activatedPom.isEmpty() ? activeByDefault : activatedPom); + activatedProfiles.addAll(activatedExternal); + + for (Profile each : activatedProfiles) { + new DefaultProfileInjector().injectProfile(nativeModel, each, null, null); + } + + return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null), + collectProfilesIds(activatedProfiles)); } + + private static Model doInterpolate(Model result, File basedir) throws RemoteException { + try { + AbstractStringBasedModelInterpolator interpolator = new CustomMaven3ModelInterpolator(new DefaultPathTranslator()); + interpolator.initialize(); + + Properties props = MavenServerUtil.collectSystemProperties(); + ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration().setExecutionProperties(props); + result = interpolator.interpolate(result, basedir, config, false); + } + catch (ModelInterpolationException e) { + Maven3ServerGlobals.getLogger().warn(e); + } + catch (InitializationException e) { + Maven3ServerGlobals.getLogger().error(e); + } + return result; + } + + private static Collection collectProfilesIds(List profiles) { + Collection result = new THashSet(); + for (Profile each : profiles) { + if (each.getId() != null) { + result.add(each.getId()); + } + } + return result; + } + + private static ProfileActivator[] getProfileActivators(File basedir) throws RemoteException { + SystemPropertyProfileActivator sysPropertyActivator = new SystemPropertyProfileActivator(); + DefaultContext context = new DefaultContext(); + context.put("SystemProperties", MavenServerUtil.collectSystemProperties()); + try { + sysPropertyActivator.contextualize(context); + } + catch (ContextException e) { + Maven3ServerGlobals.getLogger().error(e); + return new ProfileActivator[0]; + } + + return new ProfileActivator[]{new MyFileProfileActivator(basedir), + sysPropertyActivator, + new JdkPrefixProfileActivator(), + new OperatingSystemProfileActivator()}; + } + + } diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MyFileProfileActivator.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MyFileProfileActivator.java new file mode 100644 index 000000000000..d44f14e481cc --- /dev/null +++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MyFileProfileActivator.java @@ -0,0 +1,118 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.server; + +import org.apache.maven.model.Activation; +import org.apache.maven.model.ActivationFile; +import org.apache.maven.model.Profile; +import org.apache.maven.profiles.activation.DetectedProfileActivator; +import org.codehaus.plexus.interpolation.EnvarBasedValueSource; +import org.codehaus.plexus.interpolation.InterpolationException; +import org.codehaus.plexus.interpolation.MapBasedValueSource; +import org.codehaus.plexus.interpolation.RegexBasedInterpolator; +import org.codehaus.plexus.logging.LogEnabled; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.StringUtils; + +import java.io.File; +import java.io.IOException; + +/** + * Copied from org.apache.maven.profiles.activation.FileProfileActivator + * added parameter baseDit to test file existing + * + * @author Sergey Evdokimov + */ +public class MyFileProfileActivator extends DetectedProfileActivator + implements LogEnabled +{ + private Logger logger; + + private final File baseDir; + + public MyFileProfileActivator(File baseDir) { + this.baseDir = baseDir; + } + + protected boolean canDetectActivation( Profile profile ) + { + return profile.getActivation() != null && profile.getActivation().getFile() != null; + } + + public boolean isActive( Profile profile ) + { + Activation activation = profile.getActivation(); + + ActivationFile actFile = activation.getFile(); + + if ( actFile != null ) + { + // check if the file exists, if it does then the profile will be active + String fileString = actFile.getExists(); + + RegexBasedInterpolator interpolator = new RegexBasedInterpolator(); + try + { + interpolator.addValueSource( new EnvarBasedValueSource() ); + } + catch ( IOException e ) + { + // ignored + } + interpolator.addValueSource( new MapBasedValueSource( System.getProperties() ) ); + + try + { + if ( StringUtils.isNotEmpty(fileString) ) + { + fileString = StringUtils.replace( interpolator.interpolate( fileString, "" ), "\\", "/" ); + return fileExists(fileString); + } + + // check if the file is missing, if it is then the profile will be active + fileString = actFile.getMissing(); + + if ( StringUtils.isNotEmpty( fileString ) ) + { + fileString = StringUtils.replace( interpolator.interpolate( fileString, "" ), "\\", "/" ); + return !fileExists(fileString); + } + } + catch ( InterpolationException e ) + { + if ( logger.isDebugEnabled() ) + { + logger.debug( "Failed to interpolate missing file location for profile activator: " + fileString, e ); + } + else + { + logger.warn( "Failed to interpolate missing file location for profile activator: " + fileString + ". Run in debug mode (-X) for more information." ); + } + } + } + + return false; + } + + private boolean fileExists(String path) { + return new File(path).exists() || new File(baseDir, path).exists(); + } + + public void enableLogging( Logger logger ) + { + this.logger = logger; + } +} diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/FieldAccessor.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/FieldAccessor.java index c68d35e33246..bd257f669f1c 100644 --- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/FieldAccessor.java +++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/FieldAccessor.java @@ -37,7 +37,7 @@ public class FieldAccessor { return myValueCache; } - private Object getFieldValue(Class c, String fieldName, Object o) { + private static Object getFieldValue(Class c, String fieldName, Object o) { try { Field f = c.getDeclaredField(fieldName); f.setAccessible(true); @@ -52,6 +52,6 @@ public class FieldAccessor { } public static FIELD_TYPE get(Class hostClass, Object host, String fieldName) { - return new FieldAccessor(hostClass, host, fieldName).get(); + return (FIELD_TYPE)getFieldValue(hostClass, fieldName, host); } } \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java index 00d7913ad647..2a19da5789fa 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java @@ -259,9 +259,22 @@ public class MavenServerManager extends RemoteObjectWrapper { if (pluginFileOrDir.isDirectory()) { classpath.add(new File(pluginFileOrDir.getParent(), "maven-server-api")); - classpath.add(new File(pluginFileOrDir.getParent(), "maven2-server-impl")); - File luceneLib = new File(PathUtil.getJarPathForClass(Query.class)); - libDir = new File(luceneLib.getParentFile().getParentFile().getParentFile(), "maven2-server-impl/lib"); + + if (Boolean.getBoolean("idea.use.maven3")) { + classpath.add(new File(pluginFileOrDir.getParent(), "maven3-server-impl")); + File luceneLib = new File(PathUtil.getJarPathForClass(Query.class)); + + File maven3ServerRoot = new File(luceneLib.getParentFile().getParentFile().getParentFile(), "maven3-server-impl/lib/maven3"); + + libDir = new File(maven3ServerRoot, "lib"); + + classpath.add(new File(maven3ServerRoot, "boot/plexus-classworlds-2.4.jar")); + } + else { + classpath.add(new File(pluginFileOrDir.getParent(), "maven2-server-impl")); + File luceneLib = new File(PathUtil.getJarPathForClass(Query.class)); + libDir = new File(luceneLib.getParentFile().getParentFile().getParentFile(), "maven2-server-impl/lib"); + } } else { libDir = pluginFileOrDir.getParentFile();