You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PtServlet.java 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright 2014 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit.servlet;
  17. import java.io.File;
  18. import java.io.FileInputStream;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.OutputStream;
  22. import javax.servlet.ServletException;
  23. import javax.servlet.http.HttpServletRequest;
  24. import javax.servlet.http.HttpServletResponse;
  25. import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
  26. import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
  27. import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
  28. import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
  29. import org.apache.commons.compress.compressors.CompressorOutputStream;
  30. import org.apache.commons.compress.compressors.CompressorStreamFactory;
  31. import org.apache.wicket.util.io.ByteArrayOutputStream;
  32. import org.eclipse.jgit.lib.FileMode;
  33. import com.gitblit.dagger.DaggerServlet;
  34. import com.gitblit.manager.IRuntimeManager;
  35. import dagger.ObjectGraph;
  36. /**
  37. * Handles requests for the Barnum pt (patchset tool).
  38. *
  39. * The user-agent determines the content and compression format.
  40. *
  41. * @author James Moger
  42. *
  43. */
  44. public class PtServlet extends DaggerServlet {
  45. private static final long serialVersionUID = 1L;
  46. private static final long lastModified = System.currentTimeMillis();
  47. private IRuntimeManager runtimeManager;
  48. @Override
  49. protected void inject(ObjectGraph dagger) {
  50. this.runtimeManager = dagger.get(IRuntimeManager.class);
  51. }
  52. @Override
  53. protected long getLastModified(HttpServletRequest req) {
  54. File file = runtimeManager.getFileOrFolder("tickets.pt", "${baseFolder}/pt.py");
  55. if (file.exists()) {
  56. return Math.max(lastModified, file.lastModified());
  57. } else {
  58. return lastModified;
  59. }
  60. }
  61. @Override
  62. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  63. throws ServletException, IOException {
  64. try {
  65. response.setContentType("application/octet-stream");
  66. response.setDateHeader("Last-Modified", lastModified);
  67. response.setHeader("Cache-Control", "none");
  68. response.setHeader("Pragma", "no-cache");
  69. response.setDateHeader("Expires", 0);
  70. boolean windows = false;
  71. try {
  72. String useragent = request.getHeader("user-agent").toString();
  73. windows = useragent.toLowerCase().contains("windows");
  74. } catch (Exception e) {
  75. }
  76. byte[] pyBytes;
  77. File file = runtimeManager.getFileOrFolder("tickets.pt", "${baseFolder}/pt.py");
  78. if (file.exists()) {
  79. // custom script
  80. pyBytes = readAll(new FileInputStream(file));
  81. } else {
  82. // default script
  83. pyBytes = readAll(getClass().getResourceAsStream("/pt.py"));
  84. }
  85. if (windows) {
  86. // windows: download zip file with pt.py and pt.cmd
  87. response.setHeader("Content-Disposition", "attachment; filename=\"pt.zip\"");
  88. OutputStream os = response.getOutputStream();
  89. ZipArchiveOutputStream zos = new ZipArchiveOutputStream(os);
  90. // add the Python script
  91. ZipArchiveEntry pyEntry = new ZipArchiveEntry("pt.py");
  92. pyEntry.setSize(pyBytes.length);
  93. pyEntry.setUnixMode(FileMode.EXECUTABLE_FILE.getBits());
  94. pyEntry.setTime(lastModified);
  95. zos.putArchiveEntry(pyEntry);
  96. zos.write(pyBytes);
  97. zos.closeArchiveEntry();
  98. // add a Python launch cmd file
  99. byte [] cmdBytes = readAll(getClass().getResourceAsStream("/pt.cmd"));
  100. ZipArchiveEntry cmdEntry = new ZipArchiveEntry("pt.cmd");
  101. cmdEntry.setSize(cmdBytes.length);
  102. cmdEntry.setUnixMode(FileMode.REGULAR_FILE.getBits());
  103. cmdEntry.setTime(lastModified);
  104. zos.putArchiveEntry(cmdEntry);
  105. zos.write(cmdBytes);
  106. zos.closeArchiveEntry();
  107. // add a brief readme
  108. byte [] txtBytes = readAll(getClass().getResourceAsStream("/pt.txt"));
  109. ZipArchiveEntry txtEntry = new ZipArchiveEntry("readme.txt");
  110. txtEntry.setSize(txtBytes.length);
  111. txtEntry.setUnixMode(FileMode.REGULAR_FILE.getBits());
  112. txtEntry.setTime(lastModified);
  113. zos.putArchiveEntry(txtEntry);
  114. zos.write(txtBytes);
  115. zos.closeArchiveEntry();
  116. // cleanup
  117. zos.finish();
  118. zos.close();
  119. os.flush();
  120. } else {
  121. // unix: download a tar.gz file with pt.py set with execute permissions
  122. response.setHeader("Content-Disposition", "attachment; filename=\"pt.tar.gz\"");
  123. OutputStream os = response.getOutputStream();
  124. CompressorOutputStream cos = new CompressorStreamFactory().createCompressorOutputStream(CompressorStreamFactory.GZIP, os);
  125. TarArchiveOutputStream tos = new TarArchiveOutputStream(cos);
  126. tos.setAddPaxHeadersForNonAsciiNames(true);
  127. tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
  128. // add the Python script
  129. TarArchiveEntry pyEntry = new TarArchiveEntry("pt");
  130. pyEntry.setMode(FileMode.EXECUTABLE_FILE.getBits());
  131. pyEntry.setModTime(lastModified);
  132. pyEntry.setSize(pyBytes.length);
  133. tos.putArchiveEntry(pyEntry);
  134. tos.write(pyBytes);
  135. tos.closeArchiveEntry();
  136. // add a brief readme
  137. byte [] txtBytes = readAll(getClass().getResourceAsStream("/pt.txt"));
  138. TarArchiveEntry txtEntry = new TarArchiveEntry("README");
  139. txtEntry.setMode(FileMode.REGULAR_FILE.getBits());
  140. txtEntry.setModTime(lastModified);
  141. txtEntry.setSize(txtBytes.length);
  142. tos.putArchiveEntry(txtEntry);
  143. tos.write(txtBytes);
  144. tos.closeArchiveEntry();
  145. // cleanup
  146. tos.finish();
  147. tos.close();
  148. cos.close();
  149. os.flush();
  150. }
  151. } catch (Exception e) {
  152. e.printStackTrace();
  153. }
  154. }
  155. byte [] readAll(InputStream is) {
  156. ByteArrayOutputStream os = new ByteArrayOutputStream();
  157. try {
  158. byte [] buffer = new byte[4096];
  159. int len = 0;
  160. while ((len = is.read(buffer)) > -1) {
  161. os.write(buffer, 0, len);
  162. }
  163. return os.toByteArray();
  164. } catch (IOException e) {
  165. e.printStackTrace();
  166. } finally {
  167. try {
  168. os.close();
  169. is.close();
  170. } catch (Exception e) {
  171. // ignore
  172. }
  173. }
  174. return new byte[0];
  175. }
  176. }