2015年10月26日月曜日

RedmineでSVNの認証をする

タイトルの通りですが、Redmineを使用する際にSVNの認証をRedmineのデータを使ってやろうということがあると思います。
apacheを使っていればmod_perlを入れて、Redmine.pmをperl/Apacheにコピーする手順がググると出てきます。

このRedmine.pmの認証では
sub RedmineDSN {
  my ($self, $parms, $arg) = @_;
  $self->{RedmineDSN} = $arg;
  my $query = "SELECT 
                 users.hashed_password, users.salt, users.auth_source_id, roles.permissions, projects.status
              FROM projects, users, roles
              WHERE 
                users.login=? 
                AND projects.identifier=?
                AND users.status=1 
                AND (
                  roles.id IN (SELECT member_roles.role_id FROM members, member_roles WHERE members.user_id = users.id AND members.project_id = projects.id AND members.id = member_roles.member_id)
                  OR
                  (cast(projects.is_public as CHAR) IN ('t', '1')
                    AND (roles.builtin=1
                         OR roles.id IN (SELECT member_roles.role_id FROM members, member_roles, users g
                                 WHERE members.user_id = g.id AND members.project_id = projects.id AND members.id = member_roles.member_id
                                 AND g.type = 'GroupNonMember'))
                  )
                )
                AND roles.permissions IS NOT NULL";
  $self->{RedmineQuery} = trim($query);
}

こんなSQLを使っているようです。

一つのプロジェクトに複数のリポジトリを追加したんだけど、認証出来ないよ!
他のプロジェクトと同じような設定にしてるのに、なぜかこのリポジトリだけ認証できないよ!

なんていうことが起きますw

つまり、

「プロジェクトのidentifierとプロジェクトに登録したリポジトリのidentifierが同じじゃないとだめ」


ということになりますね。
このコピーしたRedmine.pmはSVNの認証用にコピーしてるわけだから、RedmineDbWhereClauseなんかちまちま変更しないで、いっそのこと直接手を加えてやればいいのです。


AND projects.identifier=?

この部分を

AND EXISTS (SELECT 'x' FROM repositories WHERE project_id = projects.id AND identifier = ?)

に変更して、apachectrl gracefulを実行すれば完了!
※PerlにコピーしたRedmine.pmを修正してください。

2015年10月25日日曜日

WindowsのVirtualBoxにCentOS7をインストールする -その2

インストールしたての状態だとイマイチ使いにくいです。
いろいろとパッケージ入ってないですしねー
とりあえず、以下のコマンドくらいはしておきます。
yum install net-tools

そしてVirtualBoxでLinuxターミナルってなんか使いにくいのでCygwinでSSHしたいw
■方法その1(アダプター1で接続)

VirtualBoxマネージャーの設定からネットワークを選択して、「ポートフォワーディング」選択して、ゲストポート22のレコードを追加します。ホストポートはあいてればなんでもいいです。

Cygwinのターミナルで接続します
$ssh -p 9000 root@localhost

■方法その2(アダプター2で接続)
CentOSでip確認をしてみます。
[root@localhost ~]# ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fe80::a00:27ff:fe5b:ba34  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:5b:ba:34  txqueuelen 1000  (Ethernet)


enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 08:00:27:75:02:e0  txqueuelen 1000  (Ethernet)


enp0s8のIPが取れていない…

vi /etc/sysconfig/network-scripts/ifcfg-enp0s8

TYPE=Ethernet
BOOTPROTO=dhcp
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=enp0s8
UUID=70b51f34-5882-43eb-b886-5d50bc177349
DEVICE=enp0s8
ONBOOT=yes

ONBOOTがnoだったのでyesに変更してネットワーク再起動します。
systemctl restart network

[root@localhost ~]# ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255


enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.56.103  netmask 255.255.255.0  broadcast 192.168.56.255
        inet6 fe80::a00:27ff:fe75:2e0  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:75:02:e0  txqueuelen 1000  (Ethernet)

IPアドレス確認できたのでCygwinからはそのIPでSSH接続します
ssh root@192.168.56.103

WindowsのVirtualBoxにCentOS7をインストールする

まずはVirtualBoxをダウンロードしてインストールします。
https://www.virtualbox.org/wiki/Downloads
インストーラーにしたがってインストールするだけです。

次に、CentOSをダウンロードします
https://www.centos.org/download/
GUI使わないならMinimal ISOが良いです。

VirtualBoxマネージャーを開いて、「新規」を押します。
名前に「CentOS」って入力するとタイプとか自動で選択されます。
メモリを適当にいじって「作成」押します。

ディスク容量を決めて「作成」押します。

VirtualBoxマネージャーに戻ったら「設定」押します。
ネットワークに「アダプター2」を有効にして、「ホストオンリーアダプター」を選ぶ。
VirtualBoxマネージャーに戻ったら「起動」押します。
ダウンロードしたCentOSのISOを選択して「起動」

そのままエンター
変な画面になるけど放置
言語を選択
「INSTALLAION DESTINATION」をクリック
変更したかったら変更してください。(何もしないでDoneしてOK)
戻ったら「NETWORK & HOST NAME」をクリック
とりあえず両方のEthernetを「ON」にする
戻ったら「SOFTWARE SELECTION」にをクリック
とりあえず「Basic Web Server」選んで適当にチェックしておく
戻ったら「Begin Installation」をクリック
インストールしてる間に、「ROOT PASSWORD」をクリック
簡単なパスワードだったりすると1回「Done」押しただけだと戻れないけど、もう1回「Done」押すと戻れます。
戻ったら「Reboot」クリック

完了!!
とりあえずログインしてみる


2015年10月18日日曜日

Eclipseのプラグインフォルダが無くなった

ちょっとした用事でJavaの開発環境を新しく構築し直すことになって最新のEclipseをダウンロードしてみました。

最近はインストーラーが用意されたんですねー
便利便利ー
(たぶんダウンロードするだけでしょうけどw)

まー、そんなこんなで、セットアップをしていくんですけど、pluginsフォルダがありません!
手動で追加しても反応しない?
pluginsが無い代わりにdropinsというフォルダがあったので、インストールしたいpluginをコピーしてみたらインストールできました。



インストーラーを使ったからなのかと思って調べたけどそれっぽい情報は出てこず。。。
でも、MARSからフォルダ構成が変わったようで、いままでのpluginsはdropinsに置き換わったそうな

2015年7月20日月曜日

Chromeのシークレットウィンドウショートカット

WEB履歴がつかないようにする時に使えるシークレットウィンドウですが、いちいちブラウザ起動して、ショートカットキーを入力するか、右クリックしてとかメニューからシークレットウィンドウを開くのが面倒なので、デスクトップショートカットから起動する方法をメモします。


これが標準的なやり方だと思います。

まず、やることは、デスクトップに普段使っているChromeのショートカットがあると思いますので、それを複製します。
次に、複製したショートカットを右クリックでプロパティーを表示します。
リンク先の部分(T)の"xxxxxxxx.exe"に注目してください。

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --incognito --profile-directory=secret

--incognito
  →シークレットウィンドウでの起動を表します。
--profile-directory=hogehoge
  →hogehogeの部分はなんでもいいですが、普段使っているユーザーとはディレクトリは分けた方がいいと思いますね。シークレットウィンドウ内だけで使いたいブックマークとかあると思いますので。。。

2015年7月8日水曜日

割り算を引き算で書いてみる

面接中に出された問題で、なんかスッキリしなかったので復習

もっといい感じに出来そうな気がするんだけどな…

public class test {
 public static void main(String[] args) {
  devide(0, 1);
  devide(5, 0);
  devide(5, 1);
  devide(5, 2);
  devide(5, 3);
  devide(5, 4);
  devide(5, 5);
  devide(5, 6);
  devide(-5, 2);
  devide(5, -2);
  devide(-5, -2);
 }

 private static void devide(int i, int j) {
  if (j == 0) {
   System.out.println("devided by 0");
   return;
  }

  int shou = 0;
  int amari = Math.abs(i);
  while (amari >= Math.abs(j)) {
   amari = amari - Math.abs(j);
   shou++;
  }
  shou = (i < 0 && j > 0) || (i > 0 && j < 0) ? -shou : shou;
  amari = i < 0 ? -amari : amari;
  System.out.println(shou == i / j && amari == i % j);
 }
}

2015年7月4日土曜日

Javaの基礎知識のメモ

Javaの開発者の面接の質問で聞かれそうな内容をまとめてみます。

オブジェクト指向-Object Oriented

設計概念で、カプセル化、多様化、継承、抽象化の特徴を持ち、メンテナンスや修正を簡単にする。
Program design concept. This has some features such as Encapsulation, Polymorphism, Inheritance and Abstraction. Those lead to easy maintenance and modification.

カプセル化-Encapsulation

オブジェクト内部の特徴や振る舞いを隠し、外部からの直接アクセスを禁止させる。
→オブジェクト同士の関係が緩くなり、修正時の影響を少なくできる
Hiding objects internal characteristic and behavior to prevent other object from changing internal contents directly.
→This aims to get relation between object loose and leads less impacts for modification.

多様化-Polymorphism

呼び出し元が振る舞いを変更するのではなく、呼び出された側が振る舞いを変更する
→分岐を減らすことができるので、修正が簡単になる
Behavior is changed not by the caller but by the callee.
→This leads to less if-statements and easy modification.

継承-Inheritance

親クラスの特徴や振る舞いを引き継ぎ、親クラスの変更をせずに自身に新たな機能を追加できる
→元のクラスの変更は無いため、修正時の影響を少なくできる
Inheriting parent class's characteristic and behavior and being able to add new functionalities to the child class it self without parent class modification.
→This leads to less impacts for modification.

抽象化-Abstraction

オブジェクトから任意の概念を抜き出し、別に抽象的なオブジェクトを作成する
→抽象的な共通モジュールを作ることで、修正が簡単になる


インターフェースとアブストラクトクラスーInterface and Abstract class


スタティックキーワードーstatic


オーバーライドとオーバーロードーOverride and Overload


コンストラクターConstructor


値渡しと参照渡しーpass by value and pass by reference



2015年6月25日木曜日

簡単!Spring framework + WebAPI + MongoDB

簡単!Spring frameworkでWEBAPIを作る
に続いて、SpringプロジェクトからNoSQLで有名なMongoDBにアクセスしてみたいと思います。
いちからプロジェクトを作ってもいいですし、WEBAPIを作った前回のプロジェクトのpom.xmlに以下を追加しても良いと思います。
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-mongodb</artifactId>
  </dependency>


まずはPCの環境に合わせてMongoDBをインストールします。
https://www.mongodb.org/downloads

WindowsならMSIのインストーラーダブルクリックで完了です。

C:\Program Files\MongoDB\Server\3.0\bin
私の環境では、ここにサーバーを起動するモジュールが入っていました。

初めての起動の前に、データフォルダを作ります。
mkdir "C:\Program Files\MongoDB\db"

Mongoサーバーを起動します。
"C:\Program Files\MongoDB\Server\3.0\bin\mongod" --dbpath "C:\Program Files\MongoDB\db"

続いて、ソースの作成

SpringでMongoDBを使うための設定をします。(XMLでやっても良いです)
java/demo/config/MongoConfig.java
package demo.config;

import java.net.UnknownHostException;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;

import com.mongodb.MongoClient;

@Configuration
public class MongoConfig {
 @Bean
 public MongoDbFactory mongoDbFactory() throws UnknownHostException {
  return new SimpleMongoDbFactory(new MongoClient("localhost", 27017), "local");
 }

 @Bean
 public MongoTemplate mongoTemplate() throws UnknownHostException {
  MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
  return mongoTemplate;
 }
}

モデルを作成します。
java/demo/model/Foo.java
package demo.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "foos")
public class Foo {
 @Id
 private String id;
 private String name;

 public String getId() {
  return id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

}
コントローラーの部分でDBにアクセスする処理を追加します。
java/demo/controller/DemoRestController.java
package demo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import demo.model.Foo;

@RestController
public class DemoRestController {
 @Autowired
 MongoTemplate mongoTemplate;

 @RequestMapping("/restdemo")
 public List<Foo> insertSelect(String name) {
  Foo foo = new Foo();
  foo.setName(name);
  // insert
  mongoTemplate.save(foo);
  // select
  List<Foo> foos = mongoTemplate.find(new Query(Criteria.where("name").is(name)), Foo.class);
  return foos;
 }
}

これで
http://localhost:8080/restdemo?name=hogehoge
にアクセスするとDBにデータがインサートされ、その結果をJSONで返す処理が完成しました。


2015年6月2日火曜日

cygwinをインストールしたら変える設定

Cygwinのターミナルでのタスクバーで右クリックすると表示optionの変更ができるようになります。

見栄えの変更

TransparencyをHighにすると微妙に透過するので少しおしゃれに見えます。

マウス操作時の変更

右クリックを押した時に「貼り付け」にするとコピペが少し早くできるようになります。

画面サイズの変更

サイズを変更して自分の好みに替えられます。


また、cygwinを起動した後のプロンプトやショートカットコマンドの設定も合わせて変更して使いやすいようにしておきましょう。

プロンプトの無駄な改行をやめる

~$ vi .bashrc
export PS1="\[\e]0;\w\a\]\[\e[32m\]\u@\h \[\e[33m\]\w\[\e[0m\]\$ "

vimの設定をする

~$ vi .vimrc
:syntax on
set nocompatible
set number

viコマンドでvimを起動する

~$ vi .bashrc
alias vi='vim'

llコマンドでls -laを表示させる

~$ vi .bashrc
alias ll='ls -la'

cygwinで最初にインストールすべきパッケージ

cygwinをふつーにセットアップすると使いたいパッケージがふくまれていないことがあるので、何をインストールすべきかまとめてみました。
  • openssh
  • gwet
  • vim
  • apt-cyg
  • git
apt-cygはsetup.exeからインストールできないので、以下のようにしてインストールします。
~$ wget https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg
--2015-06-03 08:50:25--  https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg
raw.githubusercontent.com (raw.githubusercontent.com) をDNSに問いあわせています... 103.245.222.133
raw.githubusercontent.com (raw.githubusercontent.com)|103.245.222.133|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 13620 (13K) [text/plain]
`apt-cyg' に保存中

apt-cyg                               100%[=========================================================================>]  13.30K  --.-KB/s 時間 0s

2015-06-03 08:50:28 (33.3 MB/s) - `apt-cyg' へ保存完了 [13620/13620]

~$ chmod 755 apt-cyg
~$ mv apt-cyg /usr/local/bin/

apt-cygをインストールしたらgitは以下のコマンドでインストールします。
~$ apt-cyg install git


WindowsでMacのようなターミナル -cygwin-

よくMacとWindowsでどっちが優れているかの議論で、Macは標準のターミナルでSSHができるからMacが優れているなどの意見を見たりもします。


WindowsでもSSHできるツールはたくさんありますが、LinuxライクなターミナルをWindows上で再現するのがcygwinというツールです。
https://cygwin.com/install.html



セットアップのEXEをダウンロードして実行します。
次へ
インターネットからインストールにチェックして次へ
RootDirectoryはおこのみで次へ
次へ
次へ
適当な行を選択して次へ
この画面でターミナルで使用するパッケージ(コマンド)を選択していきます。あとで足りないと思ったら再びSetup.exeを実行すればインストールできます。
たぶん、初めての人は何をインストールすればいいのか分からないかも知れません。が、それはおいおい。

デフォルトだとCygwinフォルダはC:\cygwin64になると思いますので、私はSetup.exeをここに入れて紛失しないようにしています。(間違って削除してしまっても、Cygwinのサイトからダウンロードできますけどね。。。)

2015年5月21日木曜日

Eclipseのデフォルトコンテンツアシストの挿入がうざい


これがないと開発が思うように進まないほど、頼りきってるCtrl+Spaceショートカットなんですが、デフォルトの設定のままだと、Delete/BackSpaceキーを連打するハメになることがあります。
(もしかしたら、私だけ?)


Java/Editor/ContentAssistの項目のInsertionがデフォルトだとInsertsになっています。
どちらの設定であっても、例えば、

StringUtils.isE

まで入力した後に、Ctrl+Spaceを押すと、

StringUtils.isEmpty(cs)

とcsにフォーカスがあたった状態で、入力補完が行われます。
ですが、Insertsにしていると、

StringUtils.isEmpty(cs)

と入力した後に、カーソルを「s」と「E」の間において、Ctrl+Spaceの補完でisNotEmptyにした場合、

StringUtils.isNotEmpty(cs)Empty(cs)

こうなってしまうのです!
で、Delete/BackSpaceを連打するはめに。。。

イマイチInsertsにする状況がわからないですし、Eclipseのコード補完が煩わしいと思った方はoverwritesに変更すると良いです。

簡単!Spring frameworkでWEBサイトを作る ~Jnunitテスト~

でチョー初歩的な画面を作りました。

コントローラー内で全く処理がないので、テストは伝統的にブラウザから直接開いてOKとかNGとか確認できますが、今回はテスト・ツールを使ってみます。

src/test/java/demo/DemoControllerTests.javaなるものを作ります。

package demo;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
@WebAppConfiguration
public class DemoControllerTests {
 @Autowired
 private WebApplicationContext wac;

 private MockMvc mockMvc;

 @Before
 public void setup() {
  this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
 }

 @Test
 public void getDemoPage() throws Exception {
  ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/demo?name="));
  resultActions.andExpect(MockMvcResultMatchers.status().isOk());
  resultActions.andExpect(MockMvcResultMatchers.model().attributeDoesNotExist("name"));
 }
}
とでも書いておきます。

で、実行します。
DemoControllerTestsを右クリックしてDebug As→JunitTestをクリック
グリーンなら正常、レッドなら異常になるので、常に結果がグリーンになるようにしましょう。


余談ですが、modelのattributeがnullを期待する場合のチェックは以下の様に書いておくと良いです。
resultActions.andExpect(MockMvcResultMatchers.model().attributeDoesNotExist("name"));

Eclipseのレイアウトの変更

完全に好みの世界ですが、私は以下のような設定が見やすく感じます。


  • Show print marginをONにして200列くらいにする。
  • Show whitespace charactersをONにして、改行コードを非表示にする


すると
が
な感じになります。

また、フォーマットした時の形式も変更します。
改行をさせる列数を200くらいにしちゃいます。

結局のところ何が見やすいかは自分で適当にいじくりながら探していくしかないんですよね。。。

簡単!Spring frameworkでWEBAPIを作る

に続いて、RestAPIとやらを作ってみます。



コントローラーを作成します。

package demo.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoRestController {
 @RequestMapping("/restdemo")
 public Map demo(String name) {
  Map ret = new HashMap();
  ret.put("name", name);
  List list = new ArrayList();
  list.add(name);
  list.add(name);
  ret.put("list", list);
  Map map = new HashMap();
  map.put("name", name);
  ret.put("map", map);
  return ret;
 }
}

ちょっと長いですが、「List<String>~ret.put("map", map);」の行はなくてもいいです。
また、コントローラーからの返却値をMapではなく、独自のモデルにするのもNiceな考えですね。

demo/model/DemoModel.java
package demo.model;

public class DemoModel {
 private String name;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
}

demo/controller/DemoRestController.java
package demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import demo.model.DemoModel;

@RestController
public class DemoRestController {
 @RequestMapping("/restdemo")
 public DemoModel demo(String name) {
  DemoModel ret = new DemoModel();
  ret.setName(name);
  return ret;
 }
}


で、Spring boot appを起動させて
にアクセスすると


完成!

実際にリクエストを投げてテストする時にPostmanというChromeのプラグインを使用しています。