001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.system.resolver;
019
020 import java.io.File;
021 import java.io.FileInputStream;
022 import java.io.IOException;
023 import java.io.FileOutputStream;
024 import java.util.Collection;
025 import java.util.HashMap;
026 import java.util.Map;
027 import java.util.Properties;
028
029 import org.apache.geronimo.gbean.GBeanInfo;
030 import org.apache.geronimo.gbean.GBeanInfoBuilder;
031 import org.apache.geronimo.kernel.repository.Artifact;
032 import org.apache.geronimo.kernel.repository.ArtifactManager;
033 import org.apache.geronimo.kernel.repository.ArtifactResolver;
034 import org.apache.geronimo.kernel.repository.DefaultArtifactResolver;
035 import org.apache.geronimo.kernel.repository.ListableRepository;
036 import org.apache.geronimo.system.serverinfo.ServerInfo;
037
038 /**
039 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
040 */
041 public class ExplicitDefaultArtifactResolver extends DefaultArtifactResolver implements LocalAliasedArtifactResolver {
042 private static final String COMMENT = "#You can use this file to indicate that you want to substitute one module for another.\n" +
043 "#format is oldartifactid=newartifactId e.g.\n" +
044 "#org.apache.geronimo.configs/transaction//car=org.apache.geronimo.configs/transaction-jta11/1.2-SNAPSHOT/car\n" +
045 "#versions can be ommitted on the left side but not the right.\n" +
046 "#This can also specify explicit versions in the same format.";
047
048 private final String artifactAliasesFile;
049 private final ServerInfo serverInfo;
050
051 public ExplicitDefaultArtifactResolver(String versionMapLocation,
052 ArtifactManager artifactManager,
053 Collection<? extends ListableRepository> repositories,
054 ServerInfo serverInfo ) throws IOException {
055 this(versionMapLocation, artifactManager, repositories, null, serverInfo);
056 }
057
058 public ExplicitDefaultArtifactResolver(String versionMapLocation,
059 ArtifactManager artifactManager,
060 Collection<? extends ListableRepository> repositories,
061 Map<String, String> additionalAliases,
062 ServerInfo serverInfo ) throws IOException {
063 super(artifactManager, repositories, buildExplicitResolution(versionMapLocation, additionalAliases, serverInfo));
064 this.artifactAliasesFile = versionMapLocation;
065 this.serverInfo = serverInfo;
066 }
067
068
069 public String getArtifactAliasesFile() {
070 return artifactAliasesFile;
071 }
072
073 private static Map<Artifact, Artifact> buildExplicitResolution(String versionMapLocation, Map<String, String> additionalAliases, ServerInfo serverInfo) throws IOException {
074 if (versionMapLocation == null) {
075 return null;
076 }
077 Properties properties = new Properties();
078 File location = serverInfo == null? new File(versionMapLocation): serverInfo.resolveServer(versionMapLocation);
079 if (location.exists()) {
080 FileInputStream in = new FileInputStream(location);
081 try {
082 properties.load(in);
083 } finally {
084 in.close();
085 }
086 }
087 if (additionalAliases != null) {
088 properties.putAll(additionalAliases);
089 }
090 return propertiesToArtifactMap(properties);
091 }
092
093 private static Map<Artifact, Artifact> propertiesToArtifactMap(Properties properties) {
094 Map<Artifact, Artifact> explicitResolution = new HashMap<Artifact, Artifact>();
095 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
096 String key = (String) entry.getKey();
097 String resolvedString = (String) entry.getValue();
098 Artifact source = Artifact.createPartial(key);
099 Artifact resolved = Artifact.create(resolvedString);
100 explicitResolution.put(source, resolved);
101 }
102 return explicitResolution;
103 }
104
105 private static void saveExplicitResolution(Map<Artifact, Artifact> artifactMap, String versionMapLocation, ServerInfo serverInfo) throws IOException {
106 if (versionMapLocation == null) {
107 return;
108 }
109 File location = serverInfo == null? new File(versionMapLocation): serverInfo.resolveServer(versionMapLocation);
110 if (!location.exists()) {
111 File parent = location.getParentFile();
112 if (!parent.exists() && !parent.mkdirs()) {
113 throw new IOException("Could not create directory for artifact aliases at " + parent);
114 }
115 }
116 FileOutputStream in = new FileOutputStream(location);
117 Properties properties = artifactMapToProperties(artifactMap);
118 try {
119 properties.store(in, COMMENT);
120 } finally {
121 in.close();
122 }
123 }
124
125 private static Properties artifactMapToProperties(Map<Artifact, Artifact> artifactMap) {
126 Properties properties = new Properties();
127 for (Map.Entry<Artifact, Artifact> entry: artifactMap.entrySet()) {
128 properties.setProperty(entry.getKey().toString(), entry.getValue().toString());
129 }
130 return properties;
131 }
132
133 /**
134 * Add some more artifact aliases. The plugin installer calls this
135 * TODO when a plugin is uninstalled, remove the aliases?
136 * @param properties Properties object containing the new aliases
137 * @throws IOException if the modified aliases map cannot be saved.
138 */
139 public synchronized void addAliases(Properties properties) throws IOException {
140 Map<Artifact, Artifact> explicitResolutions = propertiesToArtifactMap(properties);
141 getExplicitResolution().putAll(explicitResolutions);
142 saveExplicitResolution(getExplicitResolution(), artifactAliasesFile, serverInfo);
143 }
144
145 public static final GBeanInfo GBEAN_INFO;
146
147 static {
148 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(ExplicitDefaultArtifactResolver.class, "ArtifactResolver");
149 infoFactory.addAttribute("versionMapLocation", String.class, true, true);
150 infoFactory.addAttribute("additionalAliases", Map.class, true, true);
151 infoFactory.addReference("ArtifactManager", ArtifactManager.class, "ArtifactManager");
152 infoFactory.addReference("Repositories", ListableRepository.class, "Repository");
153 infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
154 infoFactory.addInterface(ArtifactResolver.class);
155
156 infoFactory.setConstructor(new String[]{
157 "versionMapLocation",
158 "ArtifactManager",
159 "Repositories",
160 "additionalAliases",
161 "ServerInfo"
162 });
163
164
165 GBEAN_INFO = infoFactory.getBeanInfo();
166
167 }
168
169 public static GBeanInfo getGBeanInfo() {
170 return GBEAN_INFO;
171 }
172 }