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 }