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