1   package com.atlassian.maven.plugins.amps.product;
2   
3   import com.atlassian.maven.plugins.amps.MavenContext;
4   import com.atlassian.maven.plugins.amps.MavenGoals;
5   import com.atlassian.maven.plugins.amps.Product;
6   import com.atlassian.maven.plugins.amps.ProductArtifact;
7   import com.atlassian.maven.plugins.amps.util.ConfigFileUtils.Replacement;
8   
9   import org.apache.commons.io.FileUtils;
10  import org.apache.commons.io.IOUtils;
11  import org.apache.maven.plugin.MojoExecutionException;
12  import java.io.File;
13  import java.io.IOException;
14  import java.io.InputStream;
15  import java.util.*;
16  
17  import static com.atlassian.maven.plugins.amps.util.FileUtils.fixWindowsSlashes;
18  import static java.lang.String.format;
19  
20  public class JiraProductHandler extends AbstractWebappProductHandler
21  {
22      public JiraProductHandler(final MavenContext context, final MavenGoals goals)
23      {
24          super(context, goals, new JiraPluginProvider());
25      }
26  
27      public String getId()
28      {
29          return "jira";
30      }
31  
32      @Override
33      public ProductArtifact getArtifact()
34      {
35          return new ProductArtifact("com.atlassian.jira", "atlassian-jira-webapp", "RELEASE");
36      }
37  
38      @Override
39      public ProductArtifact getTestResourcesArtifact()
40      {
41          return new ProductArtifact("com.atlassian.jira.plugins", "jira-plugin-test-resources");
42      }
43  
44      public int getDefaultHttpPort()
45      {
46          return 2990;
47      }
48  
49      protected static File getHsqlDatabaseFile(final File homeDirectory)
50      {
51          return new File(homeDirectory, "database");
52      }
53  
54      @Override
55      public Map<String, String> getSystemProperties(final Product ctx)
56      {
57          return new HashMap<String, String>()
58          {
59              {
60                  final String dburl = System.getProperty("amps.datasource.url", format("jdbc:hsqldb:%s/database", fixWindowsSlashes(getHomeDirectory(ctx).getAbsolutePath())));
61                  final String driverClass = System.getProperty("amps.datasource.driver", "org.hsqldb.jdbcDriver");
62                  final String username = System.getProperty("amps.datasource.username", "sa");
63                  final String password = System.getProperty("amps.datasource.password", "");
64                  final String datasourceTypeClass = "javax.sql.DataSource";
65  
66                  final String datasource = format("cargo.datasource.url=%s", dburl);
67                  final String driver = format("cargo.datasource.driver=%s", driverClass);
68                  final String datasourceUsername = format("cargo.datasource.username=%s", username);
69                  final String datasourcePassword = format("cargo.datasource.password=%s", password);
70                  final String datasourceType = "cargo.datasource.type=" + datasourceTypeClass;
71                  final String jndi = "cargo.datasource.jndi=jdbc/JiraDS";
72  
73                  put("jira.home", fixWindowsSlashes(getHomeDirectory(ctx).getPath()));
74                  put("cargo.datasource.datasource", format("%s|%s|%s|%s|%s|%s", datasource, driver, datasourceUsername, datasourcePassword, datasourceType, jndi));
75              }
76          };
77      }
78  
79      @Override
80      public File getUserInstalledPluginsDirectory(final File webappDir, final File homeDir)
81      {
82          return new File(new File(homeDir, "plugins"), "installed-plugins");
83      }
84  
85      @Override
86      public List<ProductArtifact> getExtraContainerDependencies()
87      {
88          return Arrays.asList(
89                  new ProductArtifact("hsqldb", "hsqldb", "1.8.0.5"),
90                  new ProductArtifact("jta", "jta", "1.0.1"),
91                  new ProductArtifact("ots-jts", "ots-jts", "1.0"),
92  
93                  // for data source and transaction manager providers
94                  new ProductArtifact("jotm", "jotm", "1.4.3"),
95                  new ProductArtifact("jotm", "jotm-jrmp_stubs", "1.4.3"),
96                  new ProductArtifact("jotm", "jotm-iiop_stubs", "1.4.3"),
97                  new ProductArtifact("jotm", "jonas_timer", "1.4.3"),
98                  new ProductArtifact("jotm", "objectweb-datasource", "1.4.3"),
99                  new ProductArtifact("carol", "carol", "1.5.2"),
100                 new ProductArtifact("carol", "carol-properties", "1.0"),
101                 new ProductArtifact("xapool", "xapool", "1.3.1"),
102                 new ProductArtifact("commons-logging", "commons-logging", "1.1.1")
103         );
104     }
105 
106     @Override
107     public String getBundledPluginPath(Product ctx)
108     {
109         // this location used from 4.1 onwards (inclusive)
110         String bundledPluginPluginsPath = "WEB-INF/classes/atlassian-bundled-plugins.zip";
111 
112     	String[] version = ctx.getVersion().split("-", 2)[0].split("\\.");
113         try
114         {
115             long major = Long.parseLong(version[0]);
116             long minor = (version.length > 1) ? Long.parseLong(version[1]) : 0;
117 
118             if (major < 4 || major == 4 && minor == 0)
119             {
120                 bundledPluginPluginsPath = "WEB-INF/classes/com/atlassian/jira/plugin/atlassian-bundled-plugins.zip";
121             }
122         }
123         catch (NumberFormatException e)
124         {
125             log.debug(String.format("Unable to parse JIRA version '%s', assuming JIRA 4.1 or newer.", ctx.getVersion()), e);
126         }
127 
128         return bundledPluginPluginsPath;
129     }
130 
131     @Override
132     public void processHomeDirectory(final Product ctx, final File homeDir) throws MojoExecutionException
133     {
134         super.processHomeDirectory(ctx, homeDir);
135         createDbConfigXmlIfNecessary(homeDir);
136     }
137 
138     @Override
139     public List<Replacement> getReplacements(Product ctx)
140     {
141         String contextPath = ctx.getContextPath();
142         if (!contextPath.startsWith("/"))
143         {
144             contextPath = "/" + contextPath;
145         }
146 
147         String baseUrl = "http://" + ctx.getServer() + ":" + ctx.getHttpPort() + contextPath;
148 
149         List<Replacement> replacements = super.getReplacements(ctx);
150         File homeDir = getHomeDirectory(ctx);
151         // We don't rewrap snapshots with these values:
152         replacements.add(0, new Replacement("http://localhost:8080", baseUrl, false));
153         replacements.add(new Replacement("@project-dir@", homeDir.getParent(), false));
154         replacements.add(new Replacement("/jira-home/", "/home/", false));
155         replacements.add(new Replacement("@base-url@",
156                 baseUrl, false));
157         return replacements;
158     }
159 
160     @Override
161     public List<File> getConfigFiles(Product product, File homeDir)
162     {
163         List<File> configFiles = super.getConfigFiles(product, homeDir);
164         configFiles.add(new File(homeDir, "database.log"));
165         configFiles.add(new File(homeDir, "database.script"));
166         configFiles.add(new File(homeDir, "dbconfig.xml"));
167         return configFiles;
168     }
169 
170     static void createDbConfigXmlIfNecessary(File homeDir) throws MojoExecutionException
171     {
172         File dbConfigXml = new File(homeDir, "dbconfig.xml");
173         if (dbConfigXml.exists())
174         {
175             return;
176         }
177 
178         InputStream templateIn = JiraProductHandler.class.getResourceAsStream("jira-dbconfig-template.xml");
179         if (templateIn == null)
180         {
181             throw new MojoExecutionException("Missing internal resource: jira-dbconfig-template.xml");
182         }
183 
184         try
185         {
186             String template = IOUtils.toString(templateIn, "utf-8");
187 
188             File dbFile = getHsqlDatabaseFile(homeDir);
189             String jdbcUrl = "jdbc:hsqldb:file:" + dbFile.toURI().getPath();
190             String result = template.replace("@jdbc-url@", jdbcUrl);
191             FileUtils.writeStringToFile(dbConfigXml, result, "utf-8");
192         }
193         catch (IOException ioe)
194         {
195             throw new MojoExecutionException("Unable to create dbconfig.xml", ioe);
196         }
197     }
198 
199     @Override
200     public List<ProductArtifact> getDefaultLibPlugins()
201     {
202         return Collections.emptyList();
203     }
204 
205     @Override
206     public List<ProductArtifact> getDefaultBundledPlugins()
207     {
208         return Collections.emptyList();
209     }
210 
211     private static class JiraPluginProvider extends AbstractPluginProvider
212     {
213 
214         @Override
215         protected Collection<ProductArtifact> getSalArtifacts(String salVersion)
216         {
217             return Arrays.asList(
218                 new ProductArtifact("com.atlassian.sal", "sal-api", salVersion),
219                 new ProductArtifact("com.atlassian.sal", "sal-jira-plugin", salVersion));
220         }
221 
222         @Override
223         protected Collection<ProductArtifact> getPdkInstallArtifacts(String pdkInstallVersion)
224         {
225             List<ProductArtifact> plugins = new ArrayList<ProductArtifact>();
226             plugins.addAll(super.getPdkInstallArtifacts(pdkInstallVersion));
227             plugins.add(new ProductArtifact("commons-fileupload", "commons-fileupload", "1.2.1"));
228             return plugins;
229         }
230     }
231 
232     @Override
233     public void cleanupProductHomeForZip(Product product, File snapshotDir) throws MojoExecutionException, IOException
234     {
235         super.cleanupProductHomeForZip(product, snapshotDir);
236 
237         FileUtils.deleteQuietly(new File(snapshotDir, "log/atlassian-jira.log"));
238     }
239 
240 
241 }