特定のクラスを継承したクラス一覧を出力する方法

掲題の通り、EclipseとかNetBeansの力を借りずにコードを書いてリストを出してみました。

guavaのClassPath使えばこんな感じで簡単に出せるようです。

package tester;

import com.google.common.reflect.ClassPath;

import java.io.IOException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.apache.struts.action.Action;

/**
 *
 * @author yushi.koga
 */
public class Main {

    public static void main(String... args) {
        try {
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            Set<Class<?>> allClasses = ClassPath.from(loader)
                    .getTopLevelClassesRecursive("my.package").stream()
                    .map(info -> info.load())
                    .collect(Collectors.toSet());
            allClasses.stream().filter((actionClass) -> (Action.class.isAssignableFrom(actionClass))).forEach((actionClass) -> {
                System.out.println(actionClass.toString());
            });

        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

RTrim最速っぽいのを簡単に調べてみた

自宅の環境(CPU:Core2 Duo E6750 メモリ4G)ではStringUtils#stripEndが最速らしい。 しかし、会社のPCではguavaが最速でした。

検証したのは、

  • 処理時に(メソッド呼ばれる毎に)で毎回Patternのインスタンス生成からやる
  • Patternの変数をstaticで持たせてインスタンス生成のコストを減らしたもの
  • StringUtils#stripEnd
  • CharMatcher#trimTrailingFrom

のどれが一番早いか!です。

結果はこちら。

検証コード

package speedcheck;

import com.google.common.base.CharMatcher;

import org.apache.commons.lang.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author yushi.koga
 */
public class SpeedCheck {

    static Pattern staticPatternForRtrim = Pattern.compile("\\s+$");
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        String sampleText = "\"aaaaaa\"    ";
        int max = 25000000;

        String staticTrimedText = null;
        System.out.println("original text start from here ->" + "\"aaaaaa\"    " + "<-to end is here");
        System.out.println("loop times : " + max);
        System.out.println("=======================================");
        long staticStarted = System.currentTimeMillis();
        for (int i = 0; i < max; i++) {
            Matcher staticMatcher = staticPatternForRtrim.matcher(sampleText);
            staticTrimedText = staticMatcher.replaceAll("");
        }
        long staticFinished = System.currentTimeMillis();
        System.out.println("staticStarted      at " + staticStarted);
        System.out.println("staticfinished     at " + staticFinished);
        System.out.println("staticPassed time  is " + ((staticFinished - staticStarted)));
        System.out.println("staticTrimedText   is " + staticTrimedText + "<- end here");
        System.out.println("=======================================");


        String insideTrimedText = null;
        long insideStarted = System.currentTimeMillis();
        for (int i = 0; i < max; i++) {
            insideTrimedText = Pattern.compile("\\s+$").matcher(sampleText).replaceAll("");
        }
        long insideFinished = System.currentTimeMillis();
        System.out.println("insideStarted      at " + insideStarted);
        System.out.println("insidefinished     at " + insideFinished);
        System.out.println("insidePassed time  is " + ((insideFinished - insideStarted)));
        System.out.println("insideTrimedText   is " + insideTrimedText + "<- end here");
        System.out.println("=======================================");


        String commonsTrimedText = null;
        long commonsStarted = System.currentTimeMillis();
        for (int i = 0; i < max; i++) {
            commonsTrimedText = StringUtils.stripEnd(sampleText," ");
        }
        long commonsFinished = System.currentTimeMillis();
        System.out.println("commonsStarted     at " + commonsStarted);
        System.out.println("commonsFinished    at " + commonsFinished);
        System.out.println("commonsPassed time is " + ((commonsFinished - commonsStarted)));
        System.out.println("commonsTrimedText  is " + commonsTrimedText + "<- end here");
        System.out.println("=======================================");


        String charMatcherTrimedText = null;
        long charMatcherStarted = System.currentTimeMillis();
        for (int i = 0; i < max; i++) {
            charMatcherTrimedText = CharMatcher.is(' ').trimTrailingFrom(sampleText);
        }
        long charMatcherFinished = System.currentTimeMillis();
        System.out.println("quavaStarted       at " + charMatcherStarted);
        System.out.println("quavaFinished      at " + charMatcherFinished);
        System.out.println("quavaPassed time   is " + ((charMatcherFinished - charMatcherStarted)));
        System.out.println("quavaTrimedText    is " + charMatcherTrimedText + "<- end here");
        System.out.println("=======================================");
    }

}

結果

Executing: gradle :run
Arguments: [-PmainClass=speedcheck.SpeedCheck, -c, D:\workspaceForNetBeans\speedcheck\settings.gradle]

:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
original text start from here ->"aaaaaa"    <-to end is here
loop times : 25000000
=======================================
staticStarted      at 1448538448194
staticfinished     at 1448538458284
staticPassed time  is 10090
staticTrimedText   is "aaaaaa"<- end here
=======================================
insideStarted      at 1448538458285
insidefinished     at 1448538479871
insidePassed time  is 21586
insideTrimedText   is "aaaaaa"<- end here
=======================================
commonsStarted     at 1448538479871
commonsFinished    at 1448538480760
commonsPassed time is 889
commonsTrimedText  is "aaaaaa"<- end here
=======================================
quavaStarted       at 1448538480760
quavaFinished      at 1448538483150
quavaPassed time   is 2390
quavaTrimedText    is "aaaaaa"<- end here
=======================================

BUILD SUCCESSFUL

Total time: 35.862 secs

どうしてもNIO2が使えないのでムシャクシャしてやった

仕事でですが、どうしてもJava6の環境で、ファイルの更新管理をするライブラリを作らなきゃいけなかったので、Apache Commons IO使って作ってみた。

github.com

参考にしたのはここです。 ありがとうございました。

qiita.com

実際に使うときはもっと修正していますが、サンプルにどうぞ。

ResourceMonitor

package sample.file.monitor.monitor;

import java.io.File;
import java.io.FileFilter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.log4j.Logger;
import sample.file.monitor.listner.ResourceListner;
import sample.file.monitor.resource.Resource;

/**
 *
 * @author yushi.koga
 */
public class ResourceMonitor {

    static private final ResourceMonitor resourceMonitor = new ResourceMonitor();
    static private final Logger log = Logger.getLogger(ResourceMonitor.class);
    private long refreshDelay = 4000L;
    private URI monitoringDirectory = null;
    static private final String MONITORING_FILE = "target.txt";

    public static ResourceMonitor getInstance() {
        return resourceMonitor;
    }

    public void setRefreshDelay(long refreshDelay) {
        this.refreshDelay = refreshDelay;
    }

    public void setMonitoringDirectory(URI monitoringDirectory) throws URISyntaxException, MalformedURLException {
        this.monitoringDirectory = monitoringDirectory;
    }

    private ResourceMonitor() {
    }

    public void start() throws ConfigurationException, MalformedURLException, Exception {
        // Guard Clause
        if (monitoringDirectory == null) {
            throw new IllegalStateException("Please set monitoring directory");
        }
        // Generate Monitor. Interval is milli seconds.
        FileAlterationMonitor monitor = new FileAlterationMonitor(refreshDelay);

        // Generate Observer.Set monitoring directory.
        final File dir = new File(monitoringDirectory);
        FileFilter filter = new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().equals(MONITORING_FILE);
            }
        };
        FileAlterationObserver observer = new FileAlterationObserver(dir, filter);

        // Generate and register Lister to Observer
        ResourceListner listener = new ResourceListner();
        observer.addListener(listener);

        // Register Observer to Monitor
        monitor.addObserver(observer);

        // Start Monitor
        Resource.load(new URL(monitoringDirectory.toURL(), MONITORING_FILE));
        monitor.start();
        log.info(this.getClass().getSimpleName() + " started monitoring");
    }
}

ResourceListner

package sample.file.monitor.listner;

import java.io.File;
import java.net.MalformedURLException;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.log4j.Logger;
import sample.file.monitor.resource.Resource;

/**
 *
 * @author yushi.koga
 */
public class ResourceListner extends FileAlterationListenerAdaptor {

    private final Logger log = Logger.getLogger(ResourceListner.class);

    private void load(File file, String event) {
        try {
            Resource.load(file.toURI().toURL());
        } catch (MalformedURLException ex) {
            log.error(file.getName() + "is " + event + "but failed to load ", ex);
        } catch (ConfigurationException ex) {
            log.error(file.getName() + "is " + event + "but failed to load ", ex);
        }
    }

    @Override
    public void onFileChange(File file) {
        log.info(file.getName() + "is updated");
        load(file, "updated");

    }

    @Override
    public void onFileCreate(File file) {
        log.info(file.getName() + "is created");
        load(file, "created");
    }

    @Override
    public void onFileDelete(File file) {
        log.info(file.getName() + "is deleted");
    }

}
Resource
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package sample.file.monitor.resource;

import java.net.URL;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.log4j.Logger;

/**
 *
 * @author yushi.koga
 */
public class Resource {

    static private final Resource resource = new Resource();
    static private final Logger log = Logger.getLogger(Resource.class);
    static private PropertiesConfiguration configuration;

    private Resource() {
    }

    public static Resource getInstance() {
        return resource;
    }

    public static void load(URL resourceFile) throws ConfigurationException{
        try {
            configuration = new PropertiesConfiguration(resourceFile);
        } catch (ConfigurationException ex) {
            log.error("failde to load " + resourceFile.toString(),ex);
            throw new ConfigurationException(ex);
        }
    }

    public String getString(String key) {
        return configuration.getString(key);
    }

    public int getInt(String key) {
        return configuration.getInt(key);
    }

    public long getLong(String key) {
        return configuration.getLong(key);
    }
}

WindowsとMacの両方でローカル配信メールを設定する方法

ローカルからアプリケーションがメール投げようとすると何も設定してないとエラーになっちゃいますよね。 私の職場じゃWindowsMac使っている人が半々なのですが、どちらの環境でもこのメールの問題を解決したので書いてみます。

Windowsの場合

簡単です。 smtp4devをダウンロードして起動するだけで25ポートをlistenしてくれます。 あとはアプリがメール投げたらこの子がそれを拾ってくれるようになります。

smtp4dev.codeplex.com

Macの場合

Macの場合は、OSがUnix系なので、postfixを設定します。 設定をすると/Users/{username}/Maildir/の配下にメールが届くようになります。 こんな感じ。

# command : create setting file for postfix
$ sudo vi /etc/postfix/aliases.reg

## discription
/(?!^root$|^{username}$)^.*$/ {username}

# command : create setting file for postfix
$ sudo vi /etc/postfix/transport_maps

## discription
/^.*@.*$/ local

# command : modify setting file for postfix
$ sudo vi /etc/postfix/main.cf

## discription
#local_recipient_maps =#local_recipient_maps =
local_recipient_maps =

#alias_maps = netinfo:/aliases#alias_maps = netinfo:/aliases
alias_maps = hash:/etc/postfix/aliases,regexp:/etc/postfix/aliases.reg

#home_mailbox = Mailbox#home_mailbox = Mailbox
home_mailbox = Maildir/

#luser_relay = admin+$local#luser_relay = admin+$local
luser_relay = {username}

# add following description to bottom line
transport_maps = pcre:/etc/postfix/transport_maps

# command : create aliases's binaly file
$ sudo postalias /etc/postfix/aliases

# command : reflect
$ sudo postfix reload

{username}は各自のユーザ名に置き換えてください。

postfixが起動してないとsudo postalias /etc/postfix/aliasesの箇所でエラーになります。

その場合は、sudo postfix startしてあげてください。

参考にしたサイトはこちら。

https://blog.tagbangers.co.jp/ja/2015/05/22/setting-of-local-e-mail-for-mac

http://open-groove.net/postfix/mail-forward/

CentOS7でLAMP環境構築(といいつつnginx)

友人のサイトのローカル環境を構築するのにLAMP環境をMacに入れたので、参考にしたサイトをメモ代わりに貼っておく。

CentOS 7 でLAMP(Nginx+MariaDB(MySQL)+PHP)インストールからWordPressを動かすまで(Nginx編) | レンタルサーバー・自宅サーバー設定・構築のヒント

Dockerエキスパート養成読本が出る!

今通ってる現場で、インフラ再構築ってことで今後はドッカー使うらしい。 ってことで勉強しとかないとついていけないので、電子書籍版出たらすぐ買う。

books.rakuten.co.jp

www.amazon.co.jp

IDEのテーマをSublime Text 3っぽく変更

NetBeans Monokai Sublime

Eclipse qiita.com

テキストエディタにはsublime text3使ってます。 これで、見た目の統一感が出た。気持ちいい!