/*******************************************************************************
* Copyright (c) 2015 IBH SYSTEMS GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBH SYSTEMS GmbH - initial API and implementation
*******************************************************************************/
package org.eclipse.packagedrone.repo.adapter.npm;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.packagedrone.repo.MetaKey;
import org.eclipse.packagedrone.repo.adapter.npm.aspect.NpmChannelAspectFactory;
import org.eclipse.packagedrone.repo.channel.ArtifactInformation;
import org.eclipse.packagedrone.repo.channel.ReadableChannel;
import org.eclipse.packagedrone.repo.manage.system.SystemService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class ModuleHandler
{
private static final MetaKey KEY_NPM_PACKAGE_JSON = new MetaKey ( NpmChannelAspectFactory.ID, "package.json" );
private static final MetaKey KEY_SHA1 = new MetaKey ( "hasher", "sha1" );
private final static Logger logger = LoggerFactory.getLogger ( ModuleHandler.class );
private final ReadableChannel channel;
private final String moduleName;
private final boolean pretty;
private final SystemService service;
public ModuleHandler ( final SystemService service, final ReadableChannel channel, final String moduleName, final boolean pretty )
{
this.service = service;
this.channel = channel;
this.moduleName = moduleName;
this.pretty = pretty;
}
public void process ( final HttpServletResponse response ) throws IOException
{
response.setContentType ( "application/json" );
process ( response.getOutputStream () );
}
private static class PackageEntry
{
private final JsonElement element;
private final PackageInfo info;
private final ArtifactInformation artifact;
public PackageEntry ( final PackageInfo info, final JsonElement element, final ArtifactInformation artifact )
{
this.info = info;
this.element = element;
this.artifact = artifact;
}
public ArtifactInformation getArtifact ()
{
return this.artifact;
}
public JsonElement getElement ()
{
return this.element;
}
public PackageInfo getInfo ()
{
return this.info;
}
}
public void process ( final OutputStream stream ) throws IOException
{
final String sitePrefix = this.service.getDefaultSitePrefix ();
final GsonBuilder builder = new GsonBuilder ();
if ( this.pretty )
{
builder.setPrettyPrinting ();
}
builder.setDateFormat ( "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" );
final Gson gson = builder.create ();
final JsonParser parser = new JsonParser ();
final TreeMap<String, PackageEntry> versions = new TreeMap<> ();
for ( final ArtifactInformation art : this.channel.getArtifacts () )
{
final String pkg = art.getMetaData ().get ( KEY_NPM_PACKAGE_JSON );
if ( pkg == null )
{
continue;
}
try
{
final JsonElement pkgEle = parser.parse ( pkg );
final PackageInfo pi = gson.fromJson ( pkgEle, PackageInfo.class );
if ( !this.moduleName.equals ( pi.getName () ) )
{
continue;
}
versions.put ( pi.getVersion (), new PackageEntry ( pi, pkgEle, art ) );
}
catch ( final Exception e )
{
logger.info ( "Failed to parse package.json of " + art.getId (), e );
continue;
}
}
// now build the main file
final JsonObject main = new JsonObject ();
// pull in meta data from most recent version
main.addProperty ( "name", this.moduleName );
if ( !versions.isEmpty () )
{
final Entry<String, PackageEntry> mostRecent = versions.lastEntry ();
final PackageInfo pi = mostRecent.getValue ().getInfo ();
main.addProperty ( "license", pi.getLicense () );
final JsonObject distTags = new JsonObject ();
main.add ( "dist-tags", distTags );
distTags.addProperty ( "latest", pi.getVersion () );
}
final JsonObject times = new JsonObject ();
main.add ( "time", times );
final JsonObject versionsEle = new JsonObject ();
main.add ( "versions", versionsEle );
for ( final Map.Entry<String, PackageEntry> entry : versions.entrySet () )
{
final PackageInfo pi = entry.getValue ().getInfo ();
final ArtifactInformation art = entry.getValue ().getArtifact ();
times.add ( pi.getVersion (), gson.toJsonTree ( art.getCreationTimestamp () ) );
final JsonObject ele = (JsonObject)entry.getValue ().getElement ();
final JsonObject dist = new JsonObject ();
dist.addProperty ( "shasum", art.getMetaData ().get ( KEY_SHA1 ) );
dist.addProperty ( "tarball", String.format ( "%s/artifact/%s/dump", sitePrefix, art.getId () ) );
ele.add ( "dist", dist );
versionsEle.add ( pi.getVersion (), ele );
}
// render
try ( OutputStreamWriter out = new OutputStreamWriter ( stream, StandardCharsets.UTF_8 ) )
{
gson.toJson ( main, out );
}
}
}