/** * Copyright (c) 2005-2017, KoLmafia development team * http://kolmafia.sourceforge.net/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * [1] Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * [2] Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * [3] Neither the name "KoLmafia" nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package net.sourceforge.kolmafia.persistence; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import net.java.dev.spellcast.utilities.LockableListModel; import net.sourceforge.kolmafia.KoLConstants; import net.sourceforge.kolmafia.StaticEntity; import net.sourceforge.kolmafia.preferences.Preferences; import net.sourceforge.kolmafia.svn.SVNManager; import net.sourceforge.kolmafia.utilities.FileUtilities; public class ScriptManager { private static class ScriptFactory { public static Script fromJSON( JSONObject jObj ) throws JSONException { String name = jObj.getString( "name" ); String repo = jObj.getString( "repo" ); String author = jObj.getString( "author" ); String category = jObj.getString( "category" ); String shortDesc = jObj.getString( "shortDesc" ); String longDesc = jObj.getString( "longDesc" ); String forumThread = jObj.getString( "forumThread" ); return new Script( name, author, shortDesc, repo, longDesc, category, forumThread ); } public static Script fromFile( File scriptFolder ) throws SVNException, JSONException { // convert the folder name to a repo. Then see if there's a matching entry in the repo file. SVNURL repo = SVNManager.workingCopyToSVNURL( scriptFolder ); JSONObject ob = repoToJSONObject( repo ); if ( ob == null ) { return fromUnknown( repo, scriptFolder ); } Script s = fromJSON( ob ); return new InstalledScript( s, scriptFolder ); } private static Script fromUnknown( SVNURL repo, File scriptFolder ) { // we can still fetch info on the repo... String uuid = SVNManager.getFolderUUIDNoRemote( repo ); return new InstalledScript( new Script( uuid, null, null, repo.toString(), null, null, null ), scriptFolder ); } private static JSONObject repoToJSONObject( SVNURL repo ) throws JSONException, SVNException { JSONArray jArray = getJSONArray(); if ( jArray == null ) return null; for ( int i = 0; i < jArray.length(); i++ ) { Object next = jArray.get( i ); if ( !( next instanceof JSONObject ) ) { throw new JSONException( "The JSON input file was not properly formatted: " + next.toString() ); } JSONObject jNext = (JSONObject) next; SVNURL fromRepo = SVNURL.parseURIEncoded( jNext.getString( "repo" ) ); if ( repo.equals( fromRepo ) ) { return jNext; } } return null; } } private static final LockableListModel<Script> installedScripts = new LockableListModel<Script>(); private static final LockableListModel<Script> repoScripts = new LockableListModel<Script>(); private static final String REPO_FILE_LOCATION = "https://raw.githubusercontent.com/balefull/kolmafiasvnrepo/master/svnrepo.json"; //this will change. static { ScriptManager.updateRepoScripts( false ); ScriptManager.updateInstalledScripts(); } public static void updateRepoScripts( boolean force ) { if ( force || !Preferences.getBoolean( "_svnRepoFileFetched" ) ) { repoScripts.clear(); FileUtilities.downloadFile( REPO_FILE_LOCATION, KoLConstants.SVN_REPO_FILE, true ); Preferences.setBoolean( "_svnRepoFileFetched", true ); } JSONArray jArray = ScriptManager.getJSONArray(); updateRepoState( jArray ); } private static JSONArray getJSONArray() { File repoFile = KoLConstants.SVN_REPO_FILE; if ( !repoFile.exists() ) return null; BufferedReader reader = FileUtilities.getReader( repoFile ); StringBuilder builder = new StringBuilder(); try { String[] data; while ( ( data = FileUtilities.readData( reader ) ) != null ) { for ( String s : data ) { builder.append( s ); } } } finally { try { reader.close(); } catch ( IOException e ) { StaticEntity.printStackTrace( e ); } } try { JSONArray jArray = new JSONArray( builder.toString() ); return jArray; } catch ( JSONException e ) { StaticEntity.printStackTrace( e ); } return null; } private static void updateRepoState( JSONArray jArray ) { if ( jArray == null ) return; ArrayList<Script> scripts = new ArrayList<Script>(); Set<SVNURL> alreadyInstalled = new HashSet<SVNURL>(); File[] currentWCs = KoLConstants.SVN_LOCATION.listFiles(); if ( currentWCs != null ) { for ( File f : currentWCs ) { if ( f.getName().startsWith( "." ) ) continue; try { alreadyInstalled.add( SVNManager.workingCopyToSVNURL( f ) ); } catch ( SVNException e ) { StaticEntity.printStackTrace( e ); } } } try { for ( int i = 0; i < jArray.length(); i++ ) { Object next = jArray.get( i ); if ( !( next instanceof JSONObject ) ) { throw new JSONException( "The JSON input file was not properly formatted: " + next.toString() ); } JSONObject jNext = (JSONObject) next; Script script = ScriptFactory.fromJSON( jNext ); // check uniqueness - if we've already installed the script, leave it out. SVNURL jRepo = SVNURL.parseURIEncoded( script.getRepo() ); if ( !alreadyInstalled.contains( jRepo ) ) scripts.add( script ); } } catch ( Exception e ) { StaticEntity.printStackTrace( e ); return; } repoScripts.clear(); repoScripts.addAll( scripts ); } public static LockableListModel<Script> getInstalledScripts() { return installedScripts; } public static void updateInstalledScripts() { installedScripts.clear(); File[] scripts = KoLConstants.SVN_LOCATION.listFiles(); if ( scripts == null ) return; for ( File script : scripts ) { if ( script.getName().startsWith( "." ) ) continue; try { installedScripts.add( ScriptFactory.fromFile( script ) ); } catch ( Exception e ) { StaticEntity.printStackTrace( e ); continue; } } } public static LockableListModel<Script> getRepoScripts( ) { return repoScripts; } }