removed jwt interface

This commit is contained in:
Walter Oggioni
2017-07-14 08:55:28 +02:00
parent 3d4b827fca
commit b79c48db25
35 changed files with 122 additions and 1235 deletions

View File

@@ -1,86 +0,0 @@
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'maven-publish'
group='org.jpacrepo'
sourceCompatibility = 1.8
logging.captureStandardOutput LogLevel.INFO
repositories {
mavenCentral()
mavenLocal()
}
test {
testLogging {
exceptionFormat = 'full'
}
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
compile 'org.apache.commons:commons-compress:1.9'
compile 'org.tukaani:xz:1.5'
compile 'javax:javaee-api:7.0'
//compile 'commons-io:commons-io:2.4'
//compile 'commons-codec:commons-codec:1.10'
compile 'eu.webtoolkit:jwt:3.3.5'
compile 'org.projectlombok:lombok:1.16.4'
//compile 'commons-fileupload:commons-fileupload:1.3.1'
//compile 'org.ops4j.orient:orient-ra-api:0.3.0'
testCompile 'com.thoughtworks.xstream:xstream:1.4.8'
testCompile 'org.jboss.resteasy:resteasy-jaxrs:3.0.11.Final'
testCompile 'org.jboss.resteasy:resteasy-client:3.0.11.Final'
testCompile 'org.jboss.resteasy:resteasy-jackson-provider:3.0.11.Final'
testCompile 'org.jboss.resteasy:resteasy-jaxb-provider:3.0.11.Final'
testCompile files('/opt/wildfly/bin/client/jboss-client.jar')
}
task deployWildfly(dependsOn: 'war') << {
def username = 'admin', password = '123456'
def sout = new StringBuffer(), serr = new StringBuffer()
def cmd = sprintf("/opt/wildfly/bin/jboss-cli.sh --controller=localhost:9990 --connect --user=%s --password=%s --command=\'deploy %s --force\'", username, password, tasks['war'].archivePath)
def proc = cmd.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitFor()
if(proc.exitValue() != 0)
{
println "$serr"
throw new RuntimeException("Error occurred during deployment")
}
}
// client.jar
task clientJar(type: Jar) {
from(sourceSets.main.output) {
archiveName project.name + "-common.jar"
include 'org/jpacrepo/model/**', 'org/jpacrepo/pacbase/**', 'org/jpacrepo/context/ApplicationContext.class'
}
}
// server.jar
task serverJar(type: Jar) {
from(sourceSets.main.output) {
}
}
publishing {
publications {
maven(MavenPublication) {
groupId project.group
artifactId project.name + "-common"
version "1.0"
artifact clientJar {
//classifier "sources"
}
}
}
}

58
build.sbt Normal file
View File

@@ -0,0 +1,58 @@
name := "jpacrepo"
organization := "com.oggio88"
version := "2.0"
resolvers += Resolver.mavenLocal
scalaVersion := "2.12.2"
libraryDependencies += "org.tukaani" % "xz" % "1.6"
libraryDependencies += "org.apache.commons" % "commons-compress" % "1.14"
libraryDependencies += "org.projectlombok" % "lombok" % "1.16.18" % "provided"
//libraryDependencies += "javax" % "javaee-api" % "7.0" % "provided"
libraryDependencies += "javax" % "javaee-api" % "7.0"
libraryDependencies += "junit" % "junit" % "4.12" % "test"
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
libraryDependencies += "com.thoughtworks.xstream" % "xstream" % "1.4.10"
libraryDependencies += "commons-io" % "commons-io" % "2.5" % "test"
//libraryDependencies += "org.jboss.resteasy" % "resteasy-jaxrs" % "3.1.3.Final" % "test"
//libraryDependencies += "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final"
//libraryDependencies += "org.jboss.resteasy" % "resteasy-jackson-provider" % "3.1.3.Final" % "test"
//libraryDependencies += "com.fasterxml.jackson.core" % "jackson-core" % "2.9.0.pr4"
//libraryDependencies += "org.jboss.resteasy" % "resteasy-jaxb-provider" % "3.1.3.Final" % "test"
//libraryDependencies += "org.jboss.spec.javax.servlet" % "jboss-servlet-api_3.1_spec" % "1.0.0.Final" % "provided"
//libraryDependencies += "org.jboss.spec.javax.ws.rs" % "jboss-jaxrs-api_2.0_spec" % "1.0.0.Final"
libraryDependencies += "org.jboss.resteasy" % "resteasy-jaxrs" % "3.0.11.Final"
libraryDependencies += "org.jboss.resteasy" % "resteasy-client" % "3.0.11.Final"
libraryDependencies += "org.jboss.resteasy" % "resteasy-jackson-provider" % "3.0.11.Final"
libraryDependencies += "org.jboss.resteasy" % "resteasy-jaxb-provider" % "3.0.11.Final"
enablePlugins(WarPlugin)
val wildflyUsername = SettingKey[String]("wildfly-username", "The account username to use to connect to wildfly with jboss-cli.sh")
val wildflyPassword = SettingKey[String]("wildfly-password", "The account password to use to connect to wildfly with jboss-cli.sh")
val wildflyURL = SettingKey[String]("wildfly-url", "The username to use to connect to wildfly with jboss-cli.sh")
wildflyUsername := "admin"
wildflyPassword := "123456"
wildflyURL := "localhost:9990"
val deploy2Wildfly = TaskKey[Unit]("deploy2Wildfly", "Deploy to a wildfly server instance", KeyRanks.ATask)
deploy2Wildfly <<= (packagedArtifact in(Compile, Keys.`package`), wildflyURL, wildflyUsername, wildflyPassword) map
{
case ((art: Artifact, warFile: File), url: String, username: String, password: String) =>
//val warFile = (artifactPath in Keys.`package` in Compile).value//(artifactPath in `package`).value.absolutePath //(packageBin in Compile).value //(artifactPath in (Compile, package)).value
val cmd = s"/opt/wildfly/bin/jboss-cli.sh --controller='${url}' --connect --user='${username}' --password='${password}' --command=\'deploy ${warFile.absolutePath} --force\'"
println(cmd)
sys.process.stringToProcess(cmd).! match
{
case 0 => "OK"
case _ => throw new RuntimeException("Error occurred during deploy")
}
}

1
project/build.properties Normal file
View File

@@ -0,0 +1 @@
sbt.version=0.13.13

1
project/plugins.sbt Normal file
View File

@@ -0,0 +1 @@
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.1.0")

View File

@@ -1,2 +0,0 @@
rootProject.name = 'jpacrepo'

View File

@@ -1,9 +1,9 @@
package org.jpacrepo.context;
package com.oggio88.jpacrepo.context;
import com.oggio88.jpacrepo.model.PkgData;
import com.oggio88.jpacrepo.service.PacmanServiceView;
import lombok.Getter;
import lombok.Setter;
import org.jpacrepo.model.PkgData;
import org.jpacrepo.service.PacmanServiceView;
import javax.enterprise.context.ApplicationScoped;
import java.io.File;

View File

@@ -1,6 +1,6 @@
package org.jpacrepo.context;
package com.oggio88.jpacrepo.context;
import org.jpacrepo.service.PacmanServiceView;
import com.oggio88.jpacrepo.service.PacmanServiceView;
import javax.ejb.EJB;
import javax.enterprise.inject.Produces;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.context;
package com.oggio88.jpacrepo.context;
import javax.inject.Qualifier;
import java.lang.annotation.ElementType;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.model;
package com.oggio88.jpacrepo.model;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.model;
package com.oggio88.jpacrepo.model;
import java.util.Date;
import javax.annotation.Generated;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.model;
package com.oggio88.jpacrepo.model;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.model;
package com.oggio88.jpacrepo.model;
import javax.persistence.Entity;
import javax.persistence.Id;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.model;
package com.oggio88.jpacrepo.model;
import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.model;
package com.oggio88.jpacrepo.model;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

View File

@@ -1,8 +1,7 @@
package org.jpacrepo.pacbase;
package com.oggio88.jpacrepo.pacbase;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.pacbase;
package com.oggio88.jpacrepo.pacbase;
import java.io.InputStream;
import java.security.DigestInputStream;

View File

@@ -1,10 +1,10 @@
package org.jpacrepo.pacbase;
package com.oggio88.jpacrepo.pacbase;
import com.oggio88.jpacrepo.model.PkgData;
import com.oggio88.jpacrepo.model.PkgName;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import org.jpacrepo.model.PkgData;
import org.jpacrepo.model.PkgName;
import java.io.File;
import java.io.FileInputStream;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.persistence;
package com.oggio88.jpacrepo.persistence;
import java.util.ArrayList;
import java.util.List;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.service;
package com.oggio88.jpacrepo.service;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

View File

@@ -1,10 +1,10 @@
package org.jpacrepo.service;
package com.oggio88.jpacrepo.service;
import org.jpacrepo.context.ApplicationContext;
import org.jpacrepo.context.DefaultConfiguration;
import org.jpacrepo.model.PkgData;
import org.jpacrepo.model.PkgName;
import org.jpacrepo.pacbase.Parser;
import com.oggio88.jpacrepo.context.ApplicationContext;
import com.oggio88.jpacrepo.context.DefaultConfiguration;
import com.oggio88.jpacrepo.model.PkgData;
import com.oggio88.jpacrepo.model.PkgName;
import com.oggio88.jpacrepo.pacbase.Parser;
import javax.annotation.Resource;
import javax.ejb.*;

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.service;
package com.oggio88.jpacrepo.service;
import javax.ejb.Remote;

View File

@@ -1,6 +1,6 @@
package org.jpacrepo.service;
package com.oggio88.jpacrepo.service;
import org.jpacrepo.model.PkgData;
import com.oggio88.jpacrepo.model.PkgData;
import javax.ejb.Local;
import java.util.List;

View File

@@ -1,14 +1,13 @@
package org.jpacrepo.service;
package com.oggio88.jpacrepo.service;
import org.apache.commons.io.IOUtils;
import org.jpacrepo.context.ApplicationContext;
import org.jpacrepo.context.DefaultConfiguration;
import org.jpacrepo.model.StringList;
import org.jpacrepo.model.PkgData;
import org.jpacrepo.model.PkgList;
import org.jpacrepo.model.PkgName;
import org.jpacrepo.pacbase.Parser;
import org.jpacrepo.persistence.QueryEngine;
import com.oggio88.jpacrepo.model.PkgName;
import com.oggio88.jpacrepo.context.ApplicationContext;
import com.oggio88.jpacrepo.context.DefaultConfiguration;
import com.oggio88.jpacrepo.model.StringList;
import com.oggio88.jpacrepo.model.PkgData;
import com.oggio88.jpacrepo.model.PkgList;
import com.oggio88.jpacrepo.pacbase.Parser;
import com.oggio88.jpacrepo.persistence.QueryEngine;
import javax.annotation.Resource;
import javax.ejb.*;
@@ -137,10 +136,12 @@ public class PacmanWebService
FileInputStream input = new FileInputStream(ctx.getFile(pkg));
try
{
byte[] bytes = new byte[128000];
while ((input.read(bytes)) != -1)
byte[] bytes = new byte[1024];
while (true)
{
output.write(bytes);
int size = input.read(bytes);
if (size < 0) break;
else output.write(bytes, 0, size);
}
output.close();
}
@@ -192,7 +193,13 @@ public class PacmanWebService
try
{
FileOutputStream fos = new FileOutputStream(file);
IOUtils.copy(input, fos);
while (true)
{
byte[] buffer = new byte[1024];
int size = input.read(buffer);
if (size < 0) break;
else fos.write(buffer, 0, size);
}
fos.close();
ut.begin();
@@ -216,7 +223,7 @@ public class PacmanWebService
{
e.printStackTrace();
Files.delete(file.toPath());
if(ut.getStatus() != Status.STATUS_NO_TRANSACTION)
if (ut.getStatus() != Status.STATUS_NO_TRANSACTION)
{
ut.rollback();
}

View File

@@ -1,4 +1,4 @@
package org.jpacrepo.util;
package com.oggio88.jpacrepo.util;
import java.io.IOException;
import java.io.InputStream;

View File

@@ -1,220 +0,0 @@
package org.jpacrepo.frontend.component;
/**
* Created by walter on 06/06/15.
*/
import eu.webtoolkit.jwt.*;
import org.jpacrepo.context.ApplicationContext;
import org.jpacrepo.model.PkgName;
import org.jpacrepo.util.Utility;
import java.util.*;
/**
* Created by walter on 03/01/15.
*/
public class JPacRepoApp extends WApplication
{
private ApplicationContext ctx;
private PackageTable table;
private WPushButton searchButton;
private WMenu pageMenu;
private WMenu pagerMenu;
private WComboBox pageCombo;
private String lastName;
private WSuggestionPopup nameSuggestion, versionSuggestion, archSuggestion;
private int pageSize = 10;
private WLineEdit packageNameEdit, packageVersionEdit, packageArchEdit;
public JPacRepoApp(WEnvironment env, ApplicationContext ctx)
{
super(env);
this.ctx = ctx;
init();
}
private void init()
{
WBootstrapTheme theme = new WBootstrapTheme();
theme.setVersion(WBootstrapTheme.Version.Version3);
setTheme(theme);
useStyleSheet(new WLink("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"));
useStyleSheet(new WLink("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css"));
require("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js");
// useStyleSheet(new WLink(WApplication.getRelativeResourcesUrl() + "/themes/bootstrap/3/bootstrap-theme.min.css"));
useStyleSheet(new WLink("css/jpacrepo-web.css"));
createView();
}
public void createView()
{
WTemplate jumbotron = new WTemplate(Utility.getTemplate("jumbotron.html"));
packageArchEdit = new WLineEdit();
packageArchEdit.setWidth(new WLength("100%"));
packageNameEdit = new WLineEdit();
packageNameEdit.setWidth(new WLength("100%"));
packageVersionEdit = new WLineEdit();
packageVersionEdit.setWidth(new WLength("100%"));
searchButton = new WPushButton("Search");
pageCombo = new WComboBox();
for (int i = 1; i <= 10; i++)
{
pageCombo.addItem(Integer.toString(i * 10));
}
searchButton.clicked().addListener(this, () ->
{
pageSize = Integer.parseInt(pageCombo.getCurrentText().toString());
while (pageMenu.getCount() > 0)
{
pageMenu.removeItem(pageMenu.itemAt(0));
}
while (pagerMenu.getCount() > 0)
{
pagerMenu.removeItem(pagerMenu.itemAt(0));
}
long resultNumber = ctx.getPacmanService().countResults(packageNameEdit.getDisplayText(), packageVersionEdit.getDisplayText(), packageArchEdit.getDisplayText());
if (resultNumber < pageSize)
{
table.showPackages(ctx.getPacmanService().searchPackage(packageNameEdit.getDisplayText(), packageVersionEdit.getDisplayText(), packageArchEdit.getDisplayText(), -1, -1));
}
else
{
int remaining = (int) resultNumber;
int i = 1;
while (remaining > 0)
{
final int logicalPageNumber = i - 1;
WMenuItem menuItem = new WMenuItem(Integer.toString(i++));
pageMenu.addItem(menuItem);
menuItem.clicked().addListener(this, () ->
{
table.showPackages(ctx.getPacmanService().searchPackage(packageNameEdit.getText(), packageVersionEdit.getText(), packageArchEdit.getText(), logicalPageNumber, pageSize));
});
remaining -= pageSize;
}
pageMenu.select(0);
WMenuItem previousItem = new WMenuItem("Previous"), nextItem = new WMenuItem("Next");
previousItem.setStyleClass("previous");
nextItem.setStyleClass("next");
previousItem.clicked().addListener(this, () ->
{
int newIndex = pageMenu.getCurrentIndex() - 1;
if (newIndex >= 0)
{
pageMenu.select(newIndex);
pageMenu.itemAt(newIndex).clicked().trigger(new WMouseEvent());
}
});
nextItem.clicked().addListener(this, () ->
{
int newIndex = pageMenu.getCurrentIndex() + 1;
if (newIndex < pageMenu.getCount())
{
pageMenu.select(newIndex);
pageMenu.itemAt(newIndex).clicked().trigger(new WMouseEvent());
}
});
pagerMenu.addItem(previousItem);
pagerMenu.addItem(nextItem);
table.showPackages(ctx.getPacmanService().searchPackage(packageNameEdit.getText(), packageVersionEdit.getText(), packageArchEdit.getText(), 0, pageSize));
}
});
table = new PackageTable();
WTemplate inputTemplate = new WTemplate(Utility.getTemplate("package-search-form.html"));
inputTemplate.bindWidget("nameInput", packageNameEdit);
inputTemplate.bindWidget("versionInput", packageVersionEdit);
inputTemplate.bindWidget("archInput", packageArchEdit);
inputTemplate.bindWidget("searchButton", searchButton);
inputTemplate.bindWidget("pageInput", pageCombo);
WContainerWidget res = new WContainerWidget();
List<PkgName> nameList = ctx.getPacmanService().listProperty("name", new HashMap<>(), PkgName.class);
List<String> nameTxtList = new ArrayList<>();
nameList.forEach((p) -> nameTxtList.add(p.id));
nameSuggestion = getSuggestionPopup(nameTxtList, res, packageNameEdit);
nameSuggestion.setFilterLength(3);
nameSuggestion.setMaximumSize(WLength.Auto, new WLength("70%"));
versionSuggestion = getSuggestionPopup(new ArrayList<>(), res, packageVersionEdit);
versionSuggestion.setMaximumSize(WLength.Auto, new WLength("70%"));
packageNameEdit.blurred().addListener(this, () ->
{
if (!packageNameEdit.getDisplayText().equals(lastName))
{
lastName = packageNameEdit.getDisplayText();
Map<String, String> predicateMap = new HashMap<>();
predicateMap.put("name", packageNameEdit.getDisplayText());
List<String> versions = ctx.getPacmanService().listProperty("version", predicateMap, String.class);
versionSuggestion.getModel().removeRows(0, versionSuggestion.getModel().getRowCount());
versions.forEach((e) -> versionSuggestion.addSuggestion(e));
packageVersionEdit.setText("");
packageArchEdit.setText("");
}
});
List<String> archs = ctx.getPacmanService().listProperty("arch", new HashMap<>(), String.class);
archSuggestion = getSuggestionPopup(archs, res, packageArchEdit);
res.addWidget(jumbotron);
res.addWidget(inputTemplate);
WContainerWidget containerWidget = new WContainerWidget();
containerWidget.addWidget(table);
containerWidget.setStyleClass("row");
res.addWidget(containerWidget);
res.setStyleClass("container main-container");
pageMenu = new WMenu();
pageMenu.setStyleClass("pagination");
res.addWidget(pageMenu);
pagerMenu = new WMenu();
pageCombo.setWidth(new WLength("100%"));
pagerMenu.setStyleClass("pager");
res.addWidget(pagerMenu);
getRoot().addWidget(res);
}
WSuggestionPopup getSuggestionPopup(List<String> suggestions, WWidget parent, WFormWidget linkedFormWidget)
{
WSuggestionPopup.Options contactOptions = new WSuggestionPopup.Options();
contactOptions.highlightBeginTag = "<u><strong>";
contactOptions.highlightEndTag = "</strong></u>";
contactOptions.listSeparator = ',';
contactOptions.whitespace = " \\n";
contactOptions.wordSeparators = "-., \"@\\n;";
//contactOptions.appendReplacedText = ", ";
WSuggestionPopup popup = new WSuggestionPopup(WSuggestionPopup
.generateMatcherJS(contactOptions), WSuggestionPopup
.generateReplacerJS(contactOptions), parent);
popup.forEdit(linkedFormWidget, EnumSet.of(WSuggestionPopup.PopupTrigger.Editing, WSuggestionPopup.PopupTrigger.DropDownIcon));
List<WString> wstrings = new ArrayList<>();
for (String suggestion : suggestions)
{
wstrings.add(new WString(suggestion));
// popup.addSuggestion(suggestion);
}
popup.setModel(new WStringListModel(wstrings));
return popup;
}
}

View File

@@ -1,82 +0,0 @@
package org.jpacrepo.frontend.component;
import eu.webtoolkit.jwt.*;
import org.jpacrepo.model.PkgData;
import java.text.DecimalFormat;
import java.util.List;
/**
* Created by walter on 06/06/15.
*/
public class PackageTable extends WTable
{
public PackageTable()
{
toggleStyleClass("table-bordered", true);
toggleStyleClass("table-condensed", true);
toggleStyleClass("table-hover", true);
}
public void showPackages(List<PkgData> pkgs)
{
clear();
setHeaderCount(1);
setWidth(new WLength("100%"));
getElementAt(0, 0).addWidget(new WText("Name"));
getElementAt(0, 1).addWidget(new WText("Version"));
getElementAt(0, 2).addWidget(new WText("Arch"));
getElementAt(0, 3).addWidget(new WText("Description"));
getElementAt(0, 4).addWidget(new WText("Size"));
getElementAt(0, 5).addWidget(new WText(""));
getElementAt(0, 5).setStyleClass("no-border");
for(int row =1 ; row<pkgs.size()+1; row++)
{
PkgData pkg = pkgs.get(row-1);
getElementAt(row, 0).addWidget(getCellText(pkg.name.id, "text-center"));
getElementAt(row, 1).addWidget(getCellText(pkg.version, "text-center"));
getElementAt(row, 2).addWidget(getCellText(pkg.arch, "text-center"));
getElementAt(row, 3).addWidget(getCellText(pkg.description, "text-center"));
getElementAt(row, 4).addWidget(getCellText(readableFileSize(pkg.size), "text-center"));
//WPushButton button = new WPushButton("Download");
WAnchor button = new WAnchor();
button.setStyleClass("btn btn-primary");
//text.setStyleClass("glyphicon glyphicon-download-alt");
// WText text = new WText();
// text.setStyleClass("glyphicons glyphicons-save");
// button.addWidget(text);
WImage img = new WImage("img/download.svg");
img.setStyleClass("download-icon");
img.setWidth(new WLength("16px"));
button.setImage(img);
button.setLink(new WLink(WLink.Type.Url, "archive/" + pkg.fileName));
button.addStyleClass("text-center");
new WText("Download",button);
getElementAt(row, 5).addWidget(button);
// getElementAt(row,5).setStyleClass("no-border");
}
}
private WText getCellText(String text, String styleClass)
{
WText res = new WText(text);
res.setWidth(new WLength("100%"));
res.setStyleClass(styleClass);
return res;
}
public static String readableFileSize(long size)
{
if (size <= 0) return "0";
final String[] units = new String[]{"B", "kB", "MB", "GB", "TB"};
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}
}

View File

@@ -1,656 +0,0 @@
package org.jpacrepo.frontend.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* <p>
* The well known "<a href="http://balusc.omnifaces.org/2009/02/fileservlet-supporting-resume-and.html">BalusC FileServlet</a>",
* as an abstract template, slightly refactored, rewritten and modernized with a.o. fast NIO stuff instead of legacy
* RandomAccessFile.
* <p>
* This servlet properly deals with <code>ETag</code>, <code>If-None-Match</code> and <code>If-Modified-Since</code>
* caching requests, hereby improving browser caching. This servlet also properly deals with <code>Range</code> and
* <code>If-Range</code> ranging requests (<a href="https://tools.ietf.org/html/rfc7233">RFC7233</a>), which is required
* by most media players for proper audio/video streaming, and by webbrowsers and for a proper resume of an paused
* download, and by download accelerators to be able to request smaller parts simultaneously. This servlet is ideal when
* you have large files like media files placed outside the web application and you can't use the default servlet.
* <p>
* <h3>Usage</h3>
* <p>
* Just extend this class and override the {@link #getFile(HttpServletRequest)} method to return the desired file. If
* you want to trigger a HTTP 400 "Bad Request" error, simply throw {@link IllegalArgumentException}. If you want to
* trigger a HTTP 404 "Not Found" error, simply return <code>null</code>, or a non-existent file.
* <p>
* Here's a concrete example which serves it via an URL like <code>/media/foo.ext</code>:
* <p>
* <pre>
* &#64;WebServlet("/media/*")
* public class MediaFileServlet extends FileServlet {
*
* private File folder;
*
* &#64;Override
* public void init() throws ServletException {
* folder = new File("/var/webapp/media");
* }
*
* &#64;Override
* protected File getFile(HttpServletRequest request) throws IllegalArgumentException {
* String pathInfo = request.getPathInfo();
*
* if (pathInfo == null || pathInfo.isEmpty() || "/".equals(pathInfo)) {
* throw new IllegalArgumentException();
* }
*
* return new File(folder, pathInfo);
* }
*
* }
* </pre>
* <p>
* You can embed it in e.g. HTML5 video tag as below:
* <pre>
* &lt;video src="#{request.contextPath}/media/video.mp4" controls="controls" /&gt;
* </pre>
* <p>
* <h3>Customizing <code>FileServlet</code></h3>
* <p>
* If more fine grained control is desired for handling "file not found" error, determining the cache expire time, the
* content type, whether the file should be supplied as an attachment and the attachment's file name, then the developer
* can opt to override one or more of the following protected methods:
* <ul>
* <li>{@link #handleFileNotFound(HttpServletRequest, HttpServletResponse)}
* <li>{@link #getExpireTime(HttpServletRequest, File)}
* <li>{@link #getContentType(HttpServletRequest, File)}
* <li>{@link #isAttachment(HttpServletRequest, String)}
* <li>{@link #getAttachmentName(HttpServletRequest, File)}
* </ul>
* <p>
* <p><strong>See also</strong>:
* <ul>
* <li><a href="http://stackoverflow.com/q/13588149/157882">How to stream audio/video files such as MP3, MP4, AVI, etc using a Servlet</a>
* <li><a href="http://stackoverflow.com/a/29991447/157882">Abstract template for a static resource servlet</a>
* </ul>
*
* @author Bauke Scholtz
* @since 2.2
*/
public abstract class AbstractFileServlet extends HttpServlet
{
// Constants ------------------------------------------------------------------------------------------------------
private static final long serialVersionUID = 1L;
private static final int DEFAULT_STREAM_BUFFER_SIZE = 10240;
private static final String ERROR_UNSUPPORTED_ENCODING = "UTF-8 is apparently not supported on this platform.";
private static final Long DEFAULT_EXPIRE_TIME_IN_SECONDS = TimeUnit.DAYS.toSeconds(30);
private static final long ONE_SECOND_IN_MILLIS = TimeUnit.SECONDS.toMillis(1);
private static final String ETAG = "W/\"%s-%s\"";
private static final Pattern RANGE_PATTERN = Pattern.compile("^bytes=[0-9]*-[0-9]*(,[0-9]*-[0-9]*)*$");
private static final String CONTENT_DISPOSITION_HEADER = "%s;filename=\"%2$s\"; filename*=UTF-8''%2$s";
private static final String MULTIPART_BOUNDARY = UUID.randomUUID().toString();
private static long stream(InputStream input, OutputStream output) throws IOException
{
try (ReadableByteChannel inputChannel = Channels.newChannel(input);
WritableByteChannel outputChannel = Channels.newChannel(output))
{
ByteBuffer buffer = ByteBuffer.allocateDirect(DEFAULT_STREAM_BUFFER_SIZE);
long size = 0;
while (inputChannel.read(buffer) != -1)
{
buffer.flip();
size += outputChannel.write(buffer);
buffer.clear();
}
return size;
}
}
/**
* Stream a specified range of the given file to the given output via NIO {@link Channels} and a directly allocated
* NIO {@link ByteBuffer}. The output stream will only implicitly be closed after streaming when the specified range
* represents the whole file, regardless of whether an exception is been thrown or not.
*
* @param file The file.
* @param output The output stream.
* @param start The start position (offset).
* @param length The (intented) length of written bytes.
* @return The (actual) length of the written bytes. This may be smaller when the given length is too large.
* @throws IOException When an I/O error occurs.
* @since 2.2
*/
public static long stream(File file, OutputStream output, long start, long length) throws IOException
{
if (start == 0 && length >= file.length())
{
return stream(new FileInputStream(file), output);
}
try (FileChannel fileChannel = (FileChannel) Files.newByteChannel(file.toPath(), StandardOpenOption.READ))
{
WritableByteChannel outputChannel = Channels.newChannel(output);
ByteBuffer buffer = ByteBuffer.allocateDirect(DEFAULT_STREAM_BUFFER_SIZE);
long size = 0;
while (fileChannel.read(buffer, start + size) != -1)
{
buffer.flip();
if (size + buffer.limit() > length)
{
buffer.limit((int) (length - size));
}
size += outputChannel.write(buffer);
if (size >= length)
{
break;
}
buffer.clear();
}
return size;
}
}
private static String encodeURL(String string)
{
if (string == null)
{
return null;
}
try
{
return URLEncoder.encode(string, UTF_8.name());
}
catch (UnsupportedEncodingException e)
{
throw new UnsupportedOperationException(ERROR_UNSUPPORTED_ENCODING, e);
}
}
private static String encodeURI(String string)
{
if (string == null)
{
return null;
}
return encodeURL(string)
.replace("+", "%20")
.replace("%21", "!")
.replace("%27", "'")
.replace("%28", "(")
.replace("%29", ")")
.replace("%7E", "~");
}
// Actions --------------------------------------------------------------------------------------------------------
@Override
protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doRequest(request, response, true);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doRequest(request, response, false);
}
private void doRequest(HttpServletRequest request, HttpServletResponse response, boolean head) throws IOException
{
response.reset();
Resource resource;
try
{
resource = new Resource(getFile(request));
}
catch (IllegalArgumentException e)
{
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if (resource.file == null)
{
handleFileNotFound(request, response);
return;
}
if (preconditionFailed(request, resource))
{
response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
return;
}
setCacheHeaders(response, resource, getExpireTime(request, resource.file));
if (notModified(request, resource))
{
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
List<Range> ranges = getRanges(request, resource);
if (ranges == null)
{
response.setHeader("Content-Range", "bytes */" + resource.length);
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return;
}
if (!ranges.isEmpty())
{
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
}
else
{
ranges.add(new Range(0, resource.length - 1)); // Full content.
}
String contentType = setContentHeaders(request, response, resource, ranges);
if (head)
{
return;
}
writeContent(response, resource, ranges, contentType);
}
/**
* Returns the file associated with the given HTTP servlet request.
* If this method throws {@link IllegalArgumentException}, then the servlet will return a HTTP 400 error.
* If this method returns <code>null</code>, or if {@link File#isFile()} returns <code>false</code>, then the
* servlet will invoke {@link #handleFileNotFound(HttpServletRequest, HttpServletResponse)}.
*
* @param request The involved HTTP servlet request.
* @return The file associated with the given HTTP servlet request.
* @throws IllegalArgumentException When the request is mangled in such way that it's not recognizable as a valid
* file request. The servlet will then return a HTTP 400 error.
*/
protected abstract File getFile(HttpServletRequest request) throws IllegalArgumentException;
/**
* Handles the case when the file is not found.
* <p>
* The default implementation sends a HTTP 404 error.
*
* @param request The involved HTTP servlet request.
* @param response The involved HTTP servlet response.
* @throws IOException When something fails at I/O level.
* @since 2.3
*/
protected void handleFileNotFound(HttpServletRequest request, HttpServletResponse response) throws IOException
{
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
/**
* Returns how long the resource may be cached by the client before it expires, in seconds.
* <p>
* The default implementation returns 30 days in seconds.
*
* @param request The involved HTTP servlet request.
* @param file The involved file.
* @return The client cache expire time in seconds (not milliseconds!).
*/
protected long getExpireTime(HttpServletRequest request, File file)
{
return DEFAULT_EXPIRE_TIME_IN_SECONDS;
}
/**
* Returns the content type associated with the given HTTP servlet request and file.
* <p>
* The default implementation delegates {@link File#getName()} to {@link ServletContext#getMimeType(String)} with a
* fallback default value of <code>application/octet-stream</code>.
*
* @param request The involved HTTP servlet request.
* @param file The involved file.
* @return The content type associated with the given HTTP servlet request and file.
*/
protected String getContentType(HttpServletRequest request, File file)
{
String type = request.getServletContext().getMimeType(file.getName());
if (type != null)
{
return type;
}
else
{
return "application/octet-stream";
}
}
/**
* Returns <code>true</code> if we must force a "Save As" dialog based on the given HTTP servlet request and content
* type as obtained from {@link #getContentType(HttpServletRequest, File)}.
* <p>
* The default implementation will return <code>true</code> if the content type does <strong>not</strong> start with
* <code>text</code> or <code>image</code>, and the <code>Accept</code> request header is either <code>null</code>
* or does not match the given content type.
*
* @param request The involved HTTP servlet request.
* @param contentType The content type of the involved file.
* @return <code>true</code> if we must force a "Save As" dialog based on the given HTTP servlet request and content
* type.
*/
protected boolean isAttachment(HttpServletRequest request, String contentType)
{
String accept = request.getHeader("Accept");
return (!contentType.startsWith("text") && !contentType.startsWith("image")) && (accept == null || !accepts(accept, contentType));
}
/**
* Returns the file name to be used in <code>Content-Disposition</code> header.
* This does not need to be URL-encoded as this will be taken care of.
* <p>
* The default implementation returns {@link File#getName()}.
*
* @param request The involved HTTP servlet request.
* @param file The involved file.
* @return The file name to be used in <code>Content-Disposition</code> header.
* @since 2.3
*/
protected String getAttachmentName(HttpServletRequest request, File file)
{
return file.getName();
}
// Sub-actions ----------------------------------------------------------------------------------------------------
/**
* Returns true if it's a conditional request which must return 412.
*/
private boolean preconditionFailed(HttpServletRequest request, Resource resource)
{
String match = request.getHeader("If-Match");
long unmodified = request.getDateHeader("If-Unmodified-Since");
return (match != null) ? !matches(match, resource.eTag) : (unmodified != -1 && modified(unmodified, resource.lastModified));
}
/**
* Set cache headers.
*/
private void setCacheHeaders(HttpServletResponse response, Resource resource, long expires)
{
//Servlets.setCacheHeaders(response, expires);
response.setHeader("ETag", resource.eTag);
response.setDateHeader("Last-Modified", resource.lastModified);
}
/**
* Returns true if it's a conditional request which must return 304.
*/
private boolean notModified(HttpServletRequest request, Resource resource)
{
String noMatch = request.getHeader("If-None-Match");
long modified = request.getDateHeader("If-Modified-Since");
return (noMatch != null) ? matches(noMatch, resource.eTag) : (modified != -1 && !modified(modified, resource.lastModified));
}
/**
* Get requested ranges. If this is null, then we must return 416. If this is empty, then we must return full file.
*/
private List<Range> getRanges(HttpServletRequest request, Resource resource)
{
List<Range> ranges = new ArrayList<>(1);
String rangeHeader = request.getHeader("Range");
if (rangeHeader == null)
{
return ranges;
}
else if (!RANGE_PATTERN.matcher(rangeHeader).matches())
{
return null; // Syntax error.
}
String ifRange = request.getHeader("If-Range");
if (ifRange != null && !ifRange.equals(resource.eTag))
{
try
{
long ifRangeTime = request.getDateHeader("If-Range");
if (ifRangeTime != -1 && modified(ifRangeTime, resource.lastModified))
{
return ranges;
}
}
catch (IllegalArgumentException ifRangeHeaderIsInvalid)
{
return ranges;
}
}
for (String rangeHeaderPart : rangeHeader.split("=")[1].split(","))
{
Range range = parseRange(rangeHeaderPart, resource.length);
if (range == null)
{
return null; // Logic error.
}
ranges.add(range);
}
return ranges;
}
/**
* Parse range header part. Returns null if there's a logic error (i.e. start after end).
*/
private Range parseRange(String range, long length)
{
long start = sublong(range, 0, range.indexOf('-'));
long end = sublong(range, range.indexOf('-') + 1, range.length());
if (start == -1)
{
start = length - end;
end = length - 1;
}
else if (end == -1 || end > length - 1)
{
end = length - 1;
}
if (start > end)
{
return null; // Logic error.
}
return new Range(start, end);
}
/**
* Set content headers.
*/
private String setContentHeaders(HttpServletRequest request, HttpServletResponse response, Resource resource, List<Range> ranges)
{
String contentType = getContentType(request, resource.file);
String disposition = isAttachment(request, contentType) ? "attachment" : "inline";
String filename = encodeURI(getAttachmentName(request, resource.file));
response.setHeader("Content-Disposition", String.format(CONTENT_DISPOSITION_HEADER, disposition, filename));
response.setHeader("Accept-Ranges", "bytes");
if (ranges.size() == 1)
{
Range range = ranges.get(0);
response.setContentType(contentType);
response.setHeader("Content-Length", String.valueOf(range.length));
if (response.getStatus() == HttpServletResponse.SC_PARTIAL_CONTENT)
{
response.setHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + resource.length);
}
}
else
{
response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
}
return contentType;
}
/**
* Write given file to response with given content type and ranges.
*/
private void writeContent(HttpServletResponse response, Resource resource, List<Range> ranges, String contentType) throws IOException
{
ServletOutputStream output = response.getOutputStream();
if (ranges.size() == 1)
{
Range range = ranges.get(0);
stream(resource.file, output, range.start, range.length);
}
else
{
for (Range range : ranges)
{
output.println();
output.println("--" + MULTIPART_BOUNDARY);
output.println("Content-Type: " + contentType);
output.println("Content-Range: bytes " + range.start + "-" + range.end + "/" + resource.length);
stream(resource.file, output, range.start, range.length);
}
output.println();
output.println("--" + MULTIPART_BOUNDARY + "--");
}
}
// Helpers --------------------------------------------------------------------------------------------------------
/**
* Returns true if the given match header matches the given ETag value.
*/
private static boolean matches(String matchHeader, String eTag)
{
String[] matchValues = matchHeader.split("\\s*,\\s*");
Arrays.sort(matchValues);
return Arrays.binarySearch(matchValues, eTag) > -1
|| Arrays.binarySearch(matchValues, "*") > -1;
}
/**
* Returns true if the given modified header is older than the given last modified value.
*/
private static boolean modified(long modifiedHeader, long lastModified)
{
return (modifiedHeader + ONE_SECOND_IN_MILLIS <= lastModified); // That second is because the header is in seconds, not millis.
}
/**
* Returns a substring of the given string value from the given begin index to the given end index as a long.
* If the substring is empty, then -1 will be returned.
*/
private static long sublong(String value, int beginIndex, int endIndex)
{
String substring = value.substring(beginIndex, endIndex);
return substring.isEmpty() ? -1 : Long.parseLong(substring);
}
/**
* Returns true if the given accept header accepts the given value.
*/
private static boolean accepts(String acceptHeader, String toAccept)
{
String[] acceptValues = acceptHeader.split("\\s*(,|;)\\s*");
Arrays.sort(acceptValues);
return Arrays.binarySearch(acceptValues, toAccept) > -1
|| Arrays.binarySearch(acceptValues, toAccept.replaceAll("/.*$", "/*")) > -1
|| Arrays.binarySearch(acceptValues, "*/*") > -1;
}
// Nested classes -------------------------------------------------------------------------------------------------
/**
* Convenience class for a file resource.
*/
private static class Resource
{
private final File file;
private final long length;
private final long lastModified;
private final String eTag;
public Resource(File file)
{
if (file != null && file.isFile())
{
this.file = file;
length = file.length();
lastModified = file.lastModified();
eTag = String.format(ETAG, encodeURL(file.getName()), lastModified);
}
else
{
this.file = null;
length = 0;
lastModified = 0;
eTag = null;
}
}
}
/**
* Convenience class for a byte range.
*/
private static class Range
{
private final long start;
private final long end;
private final long length;
public Range(long start, long end)
{
this.start = start;
this.end = end;
length = end - start + 1;
}
}
}

View File

@@ -1,38 +0,0 @@
package org.jpacrepo.frontend.servlet;
import org.jpacrepo.context.ApplicationContext;
import org.jpacrepo.context.DefaultConfiguration;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
/**
* Created by walter on 29/07/15.
*/
@WebServlet("/archive/*")
public class FileServlet extends AbstractFileServlet
{
@Inject
@DefaultConfiguration
private ApplicationContext ctx;
@Override
protected File getFile(HttpServletRequest request) throws IllegalArgumentException
{
return new File(ctx.getSystemProperties().getProperty("RepoFolder"), request.getPathInfo().substring(1));
}
}

View File

@@ -1,38 +0,0 @@
package org.jpacrepo.frontend.servlet;
import eu.webtoolkit.jwt.WApplication;
import eu.webtoolkit.jwt.WEnvironment;
import eu.webtoolkit.jwt.WtServlet;
import org.jpacrepo.context.ApplicationContext;
import org.jpacrepo.context.DefaultConfiguration;
import org.jpacrepo.frontend.component.JPacRepoApp;
import javax.inject.Inject;
import javax.servlet.annotation.WebServlet;
/**
* Created by walter on 06/06/15.
*/
@WebServlet(urlPatterns = {"/view/*"})
public class JPacRepoServlet extends WtServlet
{
@Inject
@DefaultConfiguration
ApplicationContext ctx;
private static final long serialVersionUID = 1236894561762L;
public JPacRepoServlet()
{
super();
}
@Override
public WApplication createApplication(WEnvironment env)
{
return new JPacRepoApp(env, ctx);
}
}

View File

@@ -3,16 +3,12 @@
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<listener>
<listener-class>eu.webtoolkit.jwt.ServletInit</listener-class>
</listener>
<display-name>jpacrepo</display-name>
<description>jpacrepo</description>
<!--<session-config>-->
<!--<tracking-mode>URL</tracking-mode>-->
<!--</session-config>-->
<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
<error-page>
<error-code>404</error-code>

View File

@@ -1,3 +0,0 @@
<a class="btn btn-default" href="${link}">
<span class="glyphicons glyphicon-save"></span> Download
</a>

View File

@@ -1,4 +0,0 @@
<div class="jumbotron text-center">
<h1>JPacRepo</h1>
<p>The personal archlinux package repository</p>
</div>

View File

@@ -1,46 +0,0 @@
<div class="input-control search-input">
<div class="row">
<div class="col-sm-5">
<label>
Name:
</label>
</div>
<div class="col-sm-2">
<label>
Version:
</label>
</div>
<div class="col-sm-2">
<label>
Arch:
</label>
</div>
<div class="col-sm-2">
<label>
Page size:
</label>
</div>
<div class="col-sm-1">
</div>
</div>
<div class="row">
<form class="form-inline">
<div class="form-group col-sm-5">
${nameInput}
</div>
<div class="form-group col-sm-2">
${versionInput}
</div>
<div class="form-group col-sm-2">
${archInput}
</div>
<div class="form-group col-sm-2">
${pageInput}
</div>
<div class="form-group col-sm-1">
${searchButton}
</div>
</form>
</div>
</div>

View File

@@ -2,11 +2,11 @@ import com.thoughtworks.xstream.XStream;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jpacrepo.model.PkgData;
import org.jpacrepo.pacbase.Hasher;
import org.jpacrepo.pacbase.MD5InputStream;
import org.jpacrepo.pacbase.Parser;
import org.jpacrepo.service.PacmanServiceView;
import com.oggio88.jpacrepo.model.PkgData;
import com.oggio88.jpacrepo.pacbase.Hasher;
import com.oggio88.jpacrepo.pacbase.MD5InputStream;
import com.oggio88.jpacrepo.pacbase.Parser;
import com.oggio88.jpacrepo.service.PacmanServiceView;
import org.junit.Test;
import javax.naming.*;

View File

@@ -2,11 +2,12 @@ import com.thoughtworks.xstream.XStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.jpacrepo.model.PkgData;
import org.jpacrepo.pacbase.Parser;
import com.oggio88.jpacrepo.model.PkgData;
import com.oggio88.jpacrepo.pacbase.Parser;
import org.junit.Test;
import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -19,7 +20,6 @@ public class ParseTest
// @Test
public void test() throws Exception
{
Collection<File> ls = FileUtils.listFiles(new File("/var/cache/pacman/pkg"), new RegexFileFilter(".*\\.pkg\\.tar\\.xz"), DirectoryFileFilter.DIRECTORY);
int i = 0;
List<PkgData> lista = new ArrayList<>();