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                  put("catalina.servlet.uriencoding", "UTF-8");
77              }
78          };
79      }
80  
81      @Override
82      public File getUserInstalledPluginsDirectory(final File webappDir, final File homeDir)
83      {
84          return new File(new File(homeDir, "plugins"), "installed-plugins");
85      }
86  
87      @Override
88      public List<ProductArtifact> getExtraContainerDependencies()
89      {
90          return Arrays.asList(
91                  new ProductArtifact("hsqldb", "hsqldb", "1.8.0.5"),
92                  new ProductArtifact("jta", "jta", "1.0.1"),
93                  new ProductArtifact("ots-jts", "ots-jts", "1.0"),
94  
95                  // for data source and transaction manager providers
96                  new ProductArtifact("jotm", "jotm", "1.4.3"),
97                  new ProductArtifact("jotm", "jotm-jrmp_stubs", "1.4.3"),
98                  new ProductArtifact("jotm", "jotm-iiop_stubs", "1.4.3"),
99                  new ProductArtifact("jotm", "jonas_timer", "1.4.3"),
100                 new ProductArtifact("jotm", "objectweb-datasource", "1.4.3"),
101                 new ProductArtifact("carol", "carol", "1.5.2"),
102                 new ProductArtifact("carol", "carol-properties", "1.0"),
103                 new ProductArtifact("xapool", "xapool", "1.3.1"),
104                 new ProductArtifact("commons-logging", "commons-logging", "1.1.1")
105         );
106     }
107 
108     @Override
109     public String getBundledPluginPath(Product ctx)
110     {
111         // this location used from 4.1 onwards (inclusive)
112         String bundledPluginPluginsPath = "WEB-INF/classes/atlassian-bundled-plugins.zip";
113 
114     	String[] version = ctx.getVersion().split("-", 2)[0].split("\\.");
115         try
116         {
117             long major = Long.parseLong(version[0]);
118             long minor = (version.length > 1) ? Long.parseLong(version[1]) : 0;
119 
120             if (major < 4 || major == 4 && minor == 0)
121             {
122                 bundledPluginPluginsPath = "WEB-INF/classes/com/atlassian/jira/plugin/atlassian-bundled-plugins.zip";
123             }
124         }
125         catch (NumberFormatException e)
126         {
127             log.debug(String.format("Unable to parse JIRA version '%s', assuming JIRA 4.1 or newer.", ctx.getVersion()), e);
128         }
129 
130         return bundledPluginPluginsPath;
131     }
132 
133     @Override
134     public void processHomeDirectory(final Product ctx, final File homeDir) throws MojoExecutionException
135     {
136         super.processHomeDirectory(ctx, homeDir);
137         createDbConfigXmlIfNecessary(homeDir);
138     }
139 
140     @Override
141     public List<Replacement> getReplacements(Product ctx)
142     {
143         String contextPath = ctx.getContextPath();
144         if (!contextPath.startsWith("/"))
145         {
146             contextPath = "/" + contextPath;
147         }
148 
149         String baseUrl = "http://" + ctx.getServer() + ":" + ctx.getHttpPort() + contextPath;
150 
151         List<Replacement> replacements = super.getReplacements(ctx);
152         File homeDir = getHomeDirectory(ctx);
153         // We don't rewrap snapshots with these values:
154         replacements.add(0, new Replacement("http://localhost:8080", baseUrl, false));
155         replacements.add(new Replacement("@project-dir@", homeDir.getParent(), false));
156         replacements.add(new Replacement("/jira-home/", "/home/", false));
157         replacements.add(new Replacement("@base-url@",
158                 baseUrl, false));
159         return replacements;
160     }
161 
162     @Override
163     public List<File> getConfigFiles(Product product, File homeDir)
164     {
165         List<File> configFiles = super.getConfigFiles(product, homeDir);
166         configFiles.add(new File(homeDir, "database.log"));
167         configFiles.add(new File(homeDir, "database.script"));
168         configFiles.add(new File(homeDir, "dbconfig.xml"));
169         return configFiles;
170     }
171 
172     static void createDbConfigXmlIfNecessary(File homeDir) throws MojoExecutionException
173     {
174         File dbConfigXml = new File(homeDir, "dbconfig.xml");
175         if (dbConfigXml.exists())
176         {
177             return;
178         }
179 
180         InputStream templateIn = JiraProductHandler.class.getResourceAsStream("jira-dbconfig-template.xml");
181         if (templateIn == null)
182         {
183             throw new MojoExecutionException("Missing internal resource: jira-dbconfig-template.xml");
184         }
185 
186         try
187         {
188             String template = IOUtils.toString(templateIn, "utf-8");
189 
190             File dbFile = getHsqlDatabaseFile(homeDir);
191             String jdbcUrl = "jdbc:hsqldb:file:" + dbFile.toURI().getPath();
192             String result = template.replace("@jdbc-url@", jdbcUrl);
193             FileUtils.writeStringToFile(dbConfigXml, result, "utf-8");
194         }
195         catch (IOException ioe)
196         {
197             throw new MojoExecutionException("Unable to create dbconfig.xml", ioe);
198         }
199     }
200 
201     @Override
202     public List<ProductArtifact> getDefaultLibPlugins()
203     {
204         return Collections.emptyList();
205     }
206 
207     @Override
208     public List<ProductArtifact> getDefaultBundledPlugins()
209     {
210         return Collections.emptyList();
211     }
212 
213     private static class JiraPluginProvider extends AbstractPluginProvider
214     {
215 
216         @Override
217         protected Collection<ProductArtifact> getSalArtifacts(String salVersion)
218         {
219             return Arrays.asList(
220                 new ProductArtifact("com.atlassian.sal", "sal-api", salVersion),
221                 new ProductArtifact("com.atlassian.sal", "sal-jira-plugin", salVersion));
222         }
223 
224         @Override
225         protected Collection<ProductArtifact> getPdkInstallArtifacts(String pdkInstallVersion)
226         {
227             List<ProductArtifact> plugins = new ArrayList<ProductArtifact>();
228             plugins.addAll(super.getPdkInstallArtifacts(pdkInstallVersion));
229             plugins.add(new ProductArtifact("commons-fileupload", "commons-fileupload", "1.2.1"));
230             return plugins;
231         }
232     }
233 
234     @Override
235     public void cleanupProductHomeForZip(Product product, File snapshotDir) throws MojoExecutionException, IOException
236     {
237         super.cleanupProductHomeForZip(product, snapshotDir);
238 
239         FileUtils.deleteQuietly(new File(snapshotDir, "log/atlassian-jira.log"));
240     }
241 
242 
243 }